home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr29 / memsize.zip / MEMSIZE.CPP < prev    next >
C/C++ Source or Header  |  1995-01-04  |  126KB  |  3,402 lines

  1. /**************************************************************** MEMSIZE.CPP
  2.  *                                                                          *
  3.  * System Resources Monitor                                                 *
  4.  *                                                                          *
  5.  * (C) Copyright 1991-1993 by Richard W. Papo.                              *
  6.  *                                                                          *
  7.  * This is 'FreeWare'.  As such, it may be copied and distributed           *
  8.  * freely.  If you want to use part of it in your own program, please       *
  9.  * give credit where credit is due.  If you want to change the              *
  10.  * program, please refer the change request to me or send me the            *
  11.  * modified source code.  I can be reached at CompuServe 72607,3111.        *
  12.  *                                                                          *
  13.  ****************************************************************************/
  14.  
  15. //
  16. // Things to do:
  17. //
  18. //   (1) Provide an item to serve as a button to cause a secondary
  19. //       drive status window to be displayed.
  20. //
  21. //   (2) Make file system name display optional.
  22. //
  23. //   (3) Make drive percentage utilization available as an option.
  24. //
  25. //   (4) Provide colored highlights for different levels, configurable
  26. //       by item.
  27. //
  28. //   (5) Figure out why E dies when entering its Type dialog while MEMSIZE
  29. //       or CLOCK is running.
  30. //
  31. //   (6) Provide a means to vary the priority of the monitor thread.
  32. //
  33.  
  34. #define INCL_BASE
  35. #define INCL_PM
  36. #include <os2.h>
  37.  
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41.  
  42. #include "debug.h"
  43. #include "support.h"
  44.  
  45. #include "about.h"
  46. #include "config.h"
  47. #include "process.h"
  48. #include "profile.h"
  49. #include "restring.h"
  50.  
  51. #include "items.h"
  52.  
  53. #include "memsize.h"
  54.  
  55. #define STATIC
  56.  
  57.  
  58. /****************************************************************************
  59.  *                                                                          *
  60.  *                       Definitions & Declarations                         *
  61.  *                                                                          *
  62.  ****************************************************************************/
  63.  
  64.   // Constants
  65.  
  66. #define PROGRAM_NAME       "MEMSIZE"
  67. #define CLASS_NAME          PROGRAM_NAME
  68.  
  69. #define WM_REFRESH        (WM_USER)
  70.  
  71. #define MAX_DRIVES        (26)
  72. #define DRIVE_ERROR       (0xFFFFFFFFL)
  73.  
  74. enum
  75. {
  76.   ITEM_CLOCK,
  77.   ITEM_ELAPSEDTIME,
  78.   ITEM_MEMORYFREE,
  79.   ITEM_SWAPFILESIZE,
  80.   ITEM_SWAPDISKFREE,
  81.   ITEM_SPOOLFILESIZE,
  82.   ITEM_CPULOAD,
  83.   ITEM_TASKCOUNT,
  84.   ITEM_TOTALFREE,
  85.   ITEM_BASE_COUNT
  86. } ;
  87.  
  88.  
  89.   // Data Types
  90.  
  91. typedef struct
  92. {
  93.   volatile BOOL Active ;
  94.   volatile PULONG Counter ;
  95.   PUSHORT Interval ;
  96.   HWND Owner ;
  97. }
  98. MONITOR_PARMS, *PMONITOR_PARMS ;
  99.  
  100. typedef struct
  101. {
  102.   volatile BOOL Active ;
  103.   volatile PULONG Counter ;
  104. }
  105. COUNTER_PARMS, *PCOUNTER_PARMS ;
  106.  
  107. typedef struct        // Parameters saved to system.
  108. {
  109.   // The Display Item List - - -
  110.   Item           *Items [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  111.   int             ItemCount ;
  112.  
  113.   // Data required for the display item objects to function.
  114.   ULONG           IdleCount ;
  115.   ULONG           MaxCount ;
  116.   BYTE            SwapPath [_MAX_PATH] ;
  117.   ULONG           MinFree ;
  118.   PBYTE           SpoolPath ;
  119.   COUNTRYINFO     CountryInfo ;
  120.   ResourceString *Day ;
  121.   ResourceString *Days ;
  122.   ResourceString *DaysOfWeek ;
  123.   ResourceString *DriveError ;
  124.  
  125.   // Window size and location
  126.   SWP    Position ;
  127.   BOOL   fPosition ;
  128.  
  129.   // User Options
  130.   BOOL   HideControls ;
  131.   BOOL   fHideControls ;
  132.  
  133.   BOOL   Float ;
  134.   BOOL   fFloat ;
  135.  
  136.   BOOL   Animate ;
  137.   BOOL   fAnimate ;
  138.  
  139.   USHORT TimerInterval ;
  140.   BOOL   fTimerInterval ;
  141.  
  142.   // Presentation Parameters
  143.   BYTE   FontNameSize [80] ;
  144.   BOOL   fFontNameSize ;
  145.  
  146.   COLOR  BackColor ;
  147.   BOOL   fBackColor ;
  148.  
  149.   COLOR  TextColor ;
  150.   BOOL   fTextColor ;
  151. }
  152. PROFILE, *PPROFILE ;
  153.  
  154. typedef struct        // Data structure for window.
  155. {
  156.   HAB            Anchor ;
  157.   HMODULE        Library ;
  158.   HINI           ProfileHandle ;
  159.  
  160.   ULONG          IdleCounter ;
  161.   TID            IdleLoopTID ;
  162.   COUNTER_PARMS  IdleLoopParms ;
  163.  
  164.   TID            MonitorTID ;
  165.   MONITOR_PARMS  MonitorParms ;
  166.  
  167.   PROFILE        Profile ;
  168.  
  169.   HWND           hwndTitleBar ;
  170.   HWND           hwndSysMenu ;
  171.   HWND           hwndMinMax ;
  172.  
  173.   ULONG          Drives ;
  174.  
  175.   long           Width ;
  176.   long           Height ;
  177.  
  178. }
  179. DATA, *PDATA ;
  180.  
  181. typedef struct
  182. {
  183.   HAB Anchor ;
  184.   HMODULE Library ;
  185.   HINI ProfileHandle ;
  186. }
  187. PARMS, *PPARMS ;
  188.  
  189.  
  190.   // Function Prototypes
  191.  
  192. extern INT main ( INT argc, PCHAR argv[] ) ;
  193.  
  194. STATIC MRESULT EXPENTRY MessageProcessor
  195. (
  196.   HWND hwnd,
  197.   USHORT msg,
  198.   MPARAM mp1,
  199.   MPARAM mp2
  200. ) ;
  201.  
  202. STATIC METHODFUNCTION Create ;
  203. STATIC METHODFUNCTION Destroy ;
  204. STATIC METHODFUNCTION Size ;
  205. STATIC METHODFUNCTION SaveApplication ;
  206. STATIC METHODFUNCTION Paint ;
  207. STATIC METHODFUNCTION Command ;
  208. STATIC METHODFUNCTION ResetDefaults ;
  209. STATIC METHODFUNCTION HideControlsCmd ;
  210. STATIC METHODFUNCTION Configure ;
  211. STATIC METHODFUNCTION About ;
  212. STATIC METHODFUNCTION ButtonDown ;
  213. STATIC METHODFUNCTION ButtonDblClick ;
  214. STATIC METHODFUNCTION PresParamChanged ;
  215. STATIC METHODFUNCTION SysColorChange ;
  216. STATIC METHODFUNCTION QueryKeysHelp ;
  217. STATIC METHODFUNCTION HelpError ;
  218. STATIC METHODFUNCTION ExtHelpUndefined ;
  219. STATIC METHODFUNCTION HelpSubitemNotFound ;
  220. STATIC METHODFUNCTION Refresh ;
  221.  
  222. STATIC int GetProfile ( HAB Anchor, HMODULE Library, HINI ProfileHandle, PPROFILE Profile ) ;
  223. STATIC VOID PutProfile ( HINI ProfileHandle, PPROFILE Profile ) ;
  224.  
  225. STATIC PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword ) ;
  226.  
  227. STATIC void ResizeWindow ( HWND hwnd, PPROFILE Profile ) ;
  228.  
  229. STATIC void HideControls
  230. (
  231.   BOOL fHide,
  232.   HWND hwndFrame,
  233.   HWND hwndSysMenu,
  234.   HWND hwndTitleBar,
  235.   HWND hwndMinMax
  236. ) ;
  237.  
  238. STATIC void UpdateWindow ( HWND hwnd, PDATA Data, BOOL All ) ;
  239.  
  240. STATIC VOID _Optlink MonitorLoopThread ( PVOID Parameter ) ;
  241.  
  242. STATIC VOID UpdateDriveList
  243. (
  244.   HAB Anchor,
  245.   HMODULE Library,
  246.   HINI ProfileHandle,
  247.   PPROFILE Profile,
  248.   ULONG OldDrives,
  249.   ULONG NewDrives
  250. ) ;
  251.  
  252. STATIC BOOL CheckDrive ( USHORT Drive, PBYTE FileSystem ) ;
  253.  
  254. STATIC ULONG CalibrateLoadMeter ( VOID ) ;
  255.  
  256. STATIC VOID _Optlink CounterThread ( PVOID Parameter ) ;
  257.  
  258. STATIC HINI OpenProfile ( PSZ Name, HAB Anchor, HMODULE Library, HWND HelpInstance ) ;
  259.  
  260.  
  261.   // Global Data
  262.  
  263. HMODULE Library ;
  264.  
  265.  
  266. /****************************************************************************
  267.  *                                                                          *
  268.  *      Program Mainline                                                    *
  269.  *                                                                          *
  270.  ****************************************************************************/
  271.  
  272. extern INT main ( INT argc, PCHAR argv[] )
  273. {
  274.  /***************************************************************************
  275.   * Initialize the process.                                                 *
  276.   ***************************************************************************/
  277.  
  278.   Process Proc ;
  279.  
  280.  /***************************************************************************
  281.   * Now WIN and GPI calls will work.  Open the language DLL.                *
  282.   ***************************************************************************/
  283.  
  284.   if ( DosLoadModule ( PSZ(NULL), 0, PSZ(PROGRAM_NAME), &Library ) )
  285.   {
  286.     Debug ( HWND_DESKTOP, "ERROR: Unable to load " PROGRAM_NAME ".DLL." ) ;
  287.     DosExit ( EXIT_PROCESS, 1 ) ;
  288.   }
  289.  
  290.  /***************************************************************************
  291.   * Get the program title.                                                  *
  292.   ***************************************************************************/
  293.  
  294.   ResourceString Title ( Library, IDS_TITLE ) ;
  295.  
  296.  /***************************************************************************
  297.   * Decipher command-line parameters.                                       *
  298.   ***************************************************************************/
  299.  
  300.   BOOL Reset = FALSE ;
  301.  
  302.   ResourceString ResetCommand ( Library, IDS_PARMS_RESET ) ;
  303.  
  304.   while ( --argc )
  305.   {
  306.     argv ++ ;
  307.  
  308.     WinUpper ( Proc.QueryAnchor(), 0, 0, PSZ(*argv) ) ;
  309.  
  310.     if ( *argv[0] == '?' )
  311.     {
  312.       ResourceString Message ( Library, IDS_PARAMETERLIST ) ;
  313.  
  314.       WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
  315.         PSZ(Title), 0, MB_ENTER | MB_NOICON ) ;
  316.  
  317.       DosExit ( EXIT_PROCESS, 1 ) ;
  318.     }
  319.  
  320.     if ( !strcmp ( *argv, PCHAR(ResetCommand) ) )
  321.     {
  322.       Reset = TRUE ;
  323.       continue ;
  324.     }
  325.  
  326.     {
  327.       ResourceString Format ( Library, IDS_ERROR_INVALIDPARM ) ;
  328.  
  329.       BYTE Message [200] ;
  330.       sprintf ( PCHAR(Message), PCHAR(Format), *argv ) ;
  331.  
  332.       WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  333.         PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  334.  
  335.       DosExit ( EXIT_PROCESS, 1 ) ;
  336.     }
  337.   }
  338.  
  339.  /***************************************************************************
  340.   * Create the help instance.                                               *
  341.   ***************************************************************************/
  342.  
  343.   HELPINIT HelpInit =
  344.   {
  345.     sizeof ( HELPINIT ),
  346.     0L,
  347.     PSZ(NULL),
  348.     (PHELPTABLE)MAKEULONG(ID_MAIN,0xFFFF),
  349.     NULLHANDLE,
  350.     NULLHANDLE,
  351.     0,
  352.     0,
  353.     PSZ(NULL),
  354.     CMIC_HIDE_PANEL_ID,
  355.     PSZ ( PROGRAM_NAME ".HLP" )
  356.   } ;
  357.  
  358.   ResourceString HelpTitle ( Library, IDS_HELPTITLE ) ;
  359.  
  360.   HelpInit.pszHelpWindowTitle = PSZ(HelpTitle) ;
  361.  
  362.   HWND hwndHelp = WinCreateHelpInstance ( Proc.QueryAnchor(), &HelpInit ) ;
  363.  
  364.   if ( hwndHelp == 0 )
  365.   {
  366.     ResourceString Message ( Library, IDS_ERROR_WINCREATEHELPINSTANCE ) ;
  367.  
  368.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
  369.       PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  370.   }
  371.  
  372.  /***************************************************************************
  373.   * Open/create the profile file.                                           *
  374.   ***************************************************************************/
  375.  
  376.   HINI ProfileHandle = OpenProfile ( PSZ(PROGRAM_NAME),
  377.     Proc.QueryAnchor(), Library, hwndHelp ) ;
  378.  
  379.   if ( ProfileHandle == 0 )
  380.   {
  381.     ResourceString Message ( Library, IDS_ERROR_PRFOPENPROFILE ) ;
  382.  
  383. //  Log ( "%s\r\n", PSZ(Message) ) ;
  384.  
  385.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
  386.       PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  387.  
  388.     DosFreeModule ( Library ) ;
  389.     DosExit ( EXIT_PROCESS, 1 ) ;
  390.   }
  391.  
  392.  /***************************************************************************
  393.   * If we're going to reset the program's profile, do it now.               *
  394.   ***************************************************************************/
  395.  
  396.   if ( Reset )
  397.   {
  398.     PrfWriteProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ(NULL), PSZ(NULL), 0 ) ;
  399.   }
  400.  
  401.  /***************************************************************************
  402.   * Read the profile to find out if we're to animate the frame window.      *
  403.   ***************************************************************************/
  404.  
  405.   BOOL Animate = FALSE ;
  406.   ULONG Size ;
  407.   if
  408.   (
  409.     PrfQueryProfileSize ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("Animate"), &Size )
  410.     AND
  411.     ( ( Size == sizeof(Animate) ) OR ( Size == sizeof(short) ) )
  412.     AND
  413.     PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("Animate"), &Animate, &Size )
  414.   )
  415.   {
  416.     ;
  417.   }
  418.  
  419.  /***************************************************************************
  420.   * Create the frame window.                                                *
  421.   ***************************************************************************/
  422.  
  423.   #pragma pack(2)
  424.   struct
  425.   {
  426.     USHORT Filler ;
  427.     USHORT cb ;
  428.     ULONG  flCreateFlags ;
  429.     USHORT hmodResources ;
  430.     USHORT idResources ;
  431.   }
  432.   fcdata ;
  433.   #pragma pack()
  434.  
  435.   fcdata.cb = sizeof(fcdata) - sizeof(fcdata.Filler) ;
  436.   fcdata.flCreateFlags =
  437.     FCF_TITLEBAR | FCF_SYSMENU | FCF_BORDER |
  438.     FCF_ICON | FCF_MINBUTTON | FCF_NOBYTEALIGN | FCF_ACCELTABLE ;
  439.   fcdata.hmodResources = 0 ;
  440.   fcdata.idResources = ID_MAIN ;
  441.  
  442.   HWND hwndFrame = WinCreateWindow
  443.   (
  444.     HWND_DESKTOP,
  445.     WC_FRAME,
  446.     PSZ(Title),
  447.     Animate ? WS_ANIMATE : 0,
  448.     0, 0, 0, 0,
  449.     HWND_DESKTOP,
  450.     HWND_TOP,
  451.     ID_MAIN,
  452.     &fcdata.cb,
  453.     NULL
  454.   ) ;
  455.  
  456.   if ( hwndFrame == 0 )
  457.   {
  458.     ResourceString Message ( Library, IDS_ERROR_WINCREATEFRAME ) ;
  459.  
  460.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
  461.       PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  462.  
  463.     PrfCloseProfile ( ProfileHandle ) ;
  464.     DosFreeModule ( Library ) ;
  465.     DosExit ( EXIT_PROCESS, 1 ) ;
  466.   }
  467.  
  468.  /***************************************************************************
  469.   * Associate the help instance with the frame window.                      *
  470.   ***************************************************************************/
  471.  
  472.   if ( hwndHelp )
  473.   {
  474.     WinAssociateHelpInstance ( hwndHelp, hwndFrame ) ;
  475.   }
  476.  
  477.  /***************************************************************************
  478.   * Register the window class.                                              *
  479.   ***************************************************************************/
  480.  
  481.   if ( NOT WinRegisterClass ( Proc.QueryAnchor(), PSZ(CLASS_NAME),
  482.     PFNWP(MessageProcessor), CS_MOVENOTIFY, sizeof(PVOID) ) )
  483.   {
  484.     ResourceString Format ( Library, IDS_ERROR_WINREGISTERCLASS ) ;
  485.  
  486.     BYTE Message [200] ;
  487.     sprintf ( PCHAR(Message), PCHAR(Format), CLASS_NAME ) ;
  488.  
  489.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  490.       PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  491.  
  492.     PrfCloseProfile ( ProfileHandle ) ;
  493.     DosFreeModule ( Library ) ;
  494.     DosExit ( EXIT_PROCESS, 1 ) ;
  495.   }
  496.  
  497.  /***************************************************************************
  498.   * Create client window.  If this fails, destroy frame and return.         *
  499.   ***************************************************************************/
  500.  
  501.   PARMS Parms ;
  502.   Parms.Anchor = Proc.QueryAnchor() ;
  503.   Parms.Library = Library ;
  504.   Parms.ProfileHandle = ProfileHandle ;
  505.  
  506.   HWND hwndClient = WinCreateWindow
  507.   (
  508.     hwndFrame,
  509.     PSZ(CLASS_NAME),
  510.     PSZ(""),
  511.     0,
  512.     0, 0, 0, 0,
  513.     hwndFrame,
  514.     HWND_BOTTOM,
  515.     FID_CLIENT,
  516.     &Parms,
  517.     NULL
  518.   ) ;
  519.  
  520.   if ( hwndClient == 0 )
  521.   {
  522.     ResourceString Message ( Library, IDS_ERROR_WINCREATEWINDOW ) ;
  523.  
  524.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, PSZ(Message),
  525.       PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  526.  
  527.     WinDestroyWindow ( hwndFrame ) ;
  528.     if ( hwndHelp )
  529.     {
  530.       WinDestroyHelpInstance ( hwndHelp ) ;
  531.     }
  532.     PrfCloseProfile ( ProfileHandle ) ;
  533.     DosFreeModule ( Library ) ;
  534.     DosExit ( EXIT_PROCESS, 1 ) ;
  535.   }
  536.  
  537.  /***************************************************************************
  538.   * Wait for and process messages to the window's queue.  Terminate         *
  539.   *   when the WM_QUIT message is received.                                 *
  540.   ***************************************************************************/
  541.  
  542.   QMSG QueueMessage ;
  543.   while ( WinGetMsg ( Proc.QueryAnchor(), &QueueMessage, 0, 0, 0 ) )
  544.   {
  545.     WinDispatchMsg ( Proc.QueryAnchor(), &QueueMessage ) ;
  546.   }
  547.  
  548.  /***************************************************************************
  549.   * Discard all that was requested of the system and terminate.             *
  550.   ***************************************************************************/
  551.  
  552.   WinDestroyWindow ( hwndFrame ) ;
  553.  
  554.   if ( hwndHelp )
  555.   {
  556.     WinDestroyHelpInstance ( hwndHelp ) ;
  557.   }
  558.  
  559.   PrfCloseProfile ( ProfileHandle ) ;
  560.  
  561.   DosFreeModule ( Library ) ;
  562.  
  563.   DosExit ( EXIT_PROCESS, 0 ) ;
  564. }
  565.  
  566. /****************************************************************************
  567.  *                                                                          *
  568.  *      Window Message Processor                                            *
  569.  *                                                                          *
  570.  ****************************************************************************/
  571.  
  572. STATIC MRESULT EXPENTRY MessageProcessor
  573. (
  574.   HWND hwnd,
  575.   USHORT msg,
  576.   MPARAM mp1,
  577.   MPARAM mp2
  578. )
  579. {
  580.  /***************************************************************************
  581.   * Dispatch the message according to the method table and return the       *
  582.   *   result.  Any messages not defined above get handled by the system     *
  583.   *   default window processor.                                             *
  584.   ***************************************************************************/
  585.  
  586.   static METHOD Methods [] =
  587.   {
  588.     { WM_CREATE,                Create              },
  589.     { WM_DESTROY,               Destroy             },
  590.     { WM_SIZE,                  Size                },
  591.     { WM_MOVE,                  Size                },
  592.     { WM_SAVEAPPLICATION,       SaveApplication     },
  593.     { WM_PAINT,                 Paint               },
  594.     { WM_BUTTON1DOWN,           ButtonDown          },
  595.     { WM_BUTTON2DOWN,           ButtonDown          },
  596.     { WM_BUTTON1DBLCLK,         ButtonDblClick      },
  597.     { WM_BUTTON2DBLCLK,         ButtonDblClick      },
  598.     { WM_PRESPARAMCHANGED,      PresParamChanged    },
  599.     { WM_SYSCOLORCHANGE,        SysColorChange      },
  600.     { WM_COMMAND,               Command             },
  601.     { HM_QUERY_KEYS_HELP,       QueryKeysHelp       },
  602.     { HM_ERROR,                 HelpError           },
  603.     { HM_EXT_HELP_UNDEFINED,    ExtHelpUndefined    },
  604.     { HM_HELPSUBITEM_NOT_FOUND, HelpSubitemNotFound },
  605.     { WM_REFRESH,               Refresh             }
  606.   } ;
  607.  
  608.   return ( DispatchMessage ( hwnd, msg, mp1, mp2, Methods, sizeof(Methods)/sizeof(Methods[0]), WinDefWindowProc ) ) ;
  609. }
  610.  
  611. /****************************************************************************
  612.  *                                                                          *
  613.  *      Create the main window.                                             *
  614.  *                                                                          *
  615.  ****************************************************************************/
  616.  
  617. STATIC MRESULT APIENTRY Create
  618. (
  619.   HWND hwnd,
  620.   USHORT msg,
  621.   MPARAM mp1,
  622.   MPARAM mp2
  623. )
  624. {
  625.  /***************************************************************************
  626.   * Allocate instance data.                                                 *
  627.   ***************************************************************************/
  628.  
  629.   PDATA Data = PDATA ( malloc ( sizeof(DATA) ) ) ;
  630.  
  631.   memset ( Data, 0, sizeof(DATA) ) ;
  632.  
  633.   WinSetWindowPtr ( hwnd, QWL_USER, Data ) ;
  634.  
  635.  /***************************************************************************
  636.   * Grab any parameters from the WM_CREATE message.                         *
  637.   ***************************************************************************/
  638.  
  639.   PPARMS Parms = (PPARMS) PVOIDFROMMP ( mp1 ) ;
  640.  
  641.   Data->Anchor = Parms->Anchor ;
  642.   Data->Library = Parms->Library ;
  643.   Data->ProfileHandle = Parms->ProfileHandle ;
  644.  
  645.  /***************************************************************************
  646.   * Get the current drive mask.                                             *
  647.   ***************************************************************************/
  648.  
  649.   ULONG Drive ;
  650.   DosQueryCurrentDisk ( &Drive, &Data->Drives ) ;
  651.  
  652.  /***************************************************************************
  653.   * Get profile data. Try the OS2.INI first, then try for private INI.      *
  654.   *   If obtained from OS2.INI, erase it afterwards.                        *
  655.   ***************************************************************************/
  656.  
  657.   if ( GetProfile ( Data->Anchor, Data->Library, HINI_USERPROFILE, &Data->Profile ) )
  658.   {
  659.     GetProfile ( Data->Anchor, Data->Library, Data->ProfileHandle, &Data->Profile ) ;
  660.   }
  661.   else
  662.   {
  663.     PrfWriteProfileData ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), PSZ(NULL), PSZ(NULL), 0 ) ;
  664.   }
  665.  
  666.  /***************************************************************************
  667.   * Get the frame handle.                                                   *
  668.   ***************************************************************************/
  669.  
  670.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  671.  
  672.  /***************************************************************************
  673.   * Get the control window handles.                                         *
  674.   ***************************************************************************/
  675.  
  676.   Data->hwndSysMenu  = WinWindowFromID ( hwndFrame, FID_SYSMENU  ) ;
  677.   Data->hwndTitleBar = WinWindowFromID ( hwndFrame, FID_TITLEBAR ) ;
  678.   Data->hwndMinMax   = WinWindowFromID ( hwndFrame, FID_MINMAX   ) ;
  679.  
  680.  /***************************************************************************
  681.   * Add basic extensions to the system menu.                                *
  682.   ***************************************************************************/
  683.  
  684.   static MENUITEM MenuSeparator =
  685.     { MIT_END, MIS_SEPARATOR, 0, 0, 0, 0 } ;
  686.  
  687.   AddSysMenuItem ( hwndFrame, &MenuSeparator, PSZ(NULL) ) ;
  688.  
  689.   static MENUITEM MenuItems [] =
  690.   {
  691.     { MIT_END, MIS_TEXT,      0, IDM_SAVE_APPLICATION, 0, 0 },
  692.     { MIT_END, MIS_TEXT,      0, IDM_RESET_DEFAULTS,   0, 0 },
  693.     { MIT_END, MIS_TEXT,      0, IDM_HIDE_CONTROLS,    0, 0 },
  694.     { MIT_END, MIS_TEXT,      0, IDM_CONFIGURE,        0, 0 },
  695.   } ;
  696.  
  697.   for ( int i=0; i<sizeof(MenuItems)/sizeof(MenuItems[0]); i++ )
  698.   {
  699.     ResourceString MenuText ( Data->Library, i+IDS_SAVE_APPLICATION ) ;
  700.     AddSysMenuItem ( hwndFrame, MenuItems+i, PSZ(MenuText) ) ;
  701.   }
  702.  
  703.   AddSysMenuItem ( hwndFrame, &MenuSeparator, PSZ(NULL) ) ;
  704.  
  705.  /***************************************************************************
  706.   * Add 'About' to the system menu.                                         *
  707.   ***************************************************************************/
  708.  
  709.   static MENUITEM MenuAbout =
  710.     { MIT_END, MIS_TEXT, 0, IDM_ABOUT, 0, 0 } ;
  711.  
  712.   ResourceString AboutText ( Data->Library, IDS_ABOUT ) ;
  713.  
  714.   AddSysMenuItem ( hwndFrame, &MenuAbout, PSZ(AboutText) ) ;
  715.  
  716.  /***************************************************************************
  717.   * Add 'Help' to the system menu.                                          *
  718.   ***************************************************************************/
  719.  
  720.   static MENUITEM MenuHelp =
  721.     { MIT_END, MIS_HELP, 0, 0, 0, 0 } ;
  722.  
  723.   ResourceString HelpText ( Data->Library, IDS_HELP ) ;
  724.  
  725.   AddSysMenuItem ( hwndFrame, &MenuHelp, PSZ(HelpText) ) ;
  726.  
  727.  /***************************************************************************
  728.   * Start the new load meter.                                               *
  729.   ***************************************************************************/
  730.  
  731.   Data->IdleLoopParms.Active = TRUE ;
  732.   Data->IdleLoopParms.Counter = & Data->IdleCounter ;
  733.   Data->IdleLoopTID = _beginthread ( CounterThread, NULL, 0x3000, &Data->IdleLoopParms ) ;
  734.   DosSetPrty ( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MINIMUM, Data->IdleLoopTID ) ;
  735.   DosSuspendThread ( Data->IdleLoopTID ) ;
  736.  
  737.   Data->Profile.IdleCount = 0 ;
  738.   Data->IdleCounter = 0 ;
  739.  
  740.   if ( Data->Profile.Items[ITEM_CPULOAD]->QueryFlag() )
  741.   {
  742.     DosResumeThread ( Data->IdleLoopTID ) ;
  743.   }
  744.  
  745.   Data->MonitorParms.Active = TRUE ;
  746.   Data->MonitorParms.Counter = & Data->IdleCounter ;
  747.   Data->MonitorParms.Interval = & Data->Profile.TimerInterval ;
  748.   Data->MonitorParms.Owner = hwnd ;
  749.   Data->MonitorTID = _beginthread ( MonitorLoopThread, NULL, 0x3000, &Data->MonitorParms ) ;
  750.  
  751.  /***************************************************************************
  752.   * Add the program to the system task list.                                *
  753.   ***************************************************************************/
  754.  
  755.   ResourceString Title ( Data->Library, IDS_TITLE ) ;
  756.   Add2TaskList ( hwndFrame, PSZ(Title) ) ;
  757.  
  758.  /***************************************************************************
  759.   * Position & size the window.  For some reason, we must move and size     *
  760.   *   the window to the saved position before applying the resizing         *
  761.   *   function as fine-tuning.  Maybe the positioning request fails if      *
  762.   *   the window has no size?                                               *
  763.   ***************************************************************************/
  764.  
  765.   WinSetWindowPos ( hwndFrame, HWND_BOTTOM,
  766.     Data->Profile.Position.x, Data->Profile.Position.y,
  767.     Data->Profile.Position.cx, Data->Profile.Position.cy,
  768.     SWP_SIZE | SWP_MOVE | SWP_ZORDER |
  769.     ( Data->Profile.Position.fl & SWP_MINIMIZE ) |
  770.     ( Data->Profile.Position.fl & SWP_RESTORE ) ) ;
  771.  
  772.   ResizeWindow ( hwnd, &Data->Profile ) ;
  773.  
  774.  /***************************************************************************
  775.   * Hide the controls if so configured.                                     *
  776.   ***************************************************************************/
  777.  
  778.   if ( Data->Profile.HideControls
  779.     AND NOT ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  780.   {
  781.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  782.  
  783.     HideControls
  784.     (
  785.       TRUE,
  786.       hwndFrame,
  787.       Data->hwndSysMenu,
  788.       Data->hwndTitleBar,
  789.       Data->hwndMinMax
  790.     ) ;
  791.   }
  792.  
  793.  /***************************************************************************
  794.   * Get the saved presentation parameters and reinstate them.               *
  795.   ***************************************************************************/
  796.  
  797.   if ( Data->Profile.fFontNameSize )
  798.   {
  799.     WinSetPresParam ( hwnd, PP_FONTNAMESIZE,
  800.       strlen(PCHAR(Data->Profile.FontNameSize))+1, Data->Profile.FontNameSize ) ;
  801.   }
  802.  
  803.   if ( Data->Profile.fBackColor )
  804.   {
  805.     WinSetPresParam ( hwnd, PP_BACKGROUNDCOLOR,
  806.       sizeof(Data->Profile.BackColor), &Data->Profile.BackColor ) ;
  807.   }
  808.  
  809.   if ( Data->Profile.fTextColor )
  810.   {
  811.     WinSetPresParam ( hwnd, PP_FOREGROUNDCOLOR,
  812.       sizeof(Data->Profile.TextColor), &Data->Profile.TextColor ) ;
  813.   }
  814.  
  815.  /***************************************************************************
  816.   * Determine our font size.                                                *
  817.   ***************************************************************************/
  818.  
  819.   HPS hPS = WinGetPS ( hwnd ) ;
  820.   RECTL Rectangle ;
  821.   WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  822.   WinDrawText ( hPS, 1, PSZ(" "), &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  823.   Data->Width  = Rectangle.xRight - Rectangle.xLeft ;
  824.   Data->Height = Rectangle.yTop - Rectangle.yBottom ;
  825.   WinReleasePS ( hPS ) ;
  826.  
  827.  /***************************************************************************
  828.   * Now that the window's in order, make it visible.                        *
  829.   ***************************************************************************/
  830.  
  831.   WinShowWindow ( hwndFrame, TRUE ) ;
  832.  
  833.  /***************************************************************************
  834.   * Success?  Return no error.                                              *
  835.   ***************************************************************************/
  836.  
  837.   return ( 0 ) ;
  838. }
  839.  
  840. /****************************************************************************
  841.  *                                                                          *
  842.  *      Destroy main window.                                                *
  843.  *                                                                          *
  844.  ****************************************************************************/
  845.  
  846. STATIC MRESULT APIENTRY Destroy
  847. (
  848.   HWND hwnd,
  849.   USHORT msg,
  850.   MPARAM mp1,
  851.   MPARAM mp2
  852. )
  853. {
  854.  /***************************************************************************
  855.   * Find the instance data.                                                 *
  856.   ***************************************************************************/
  857.  
  858.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  859.  
  860.  /***************************************************************************
  861.   * Kill the extra threads.                                                 *
  862.   ***************************************************************************/
  863.  
  864.   DosResumeThread ( Data->MonitorTID ) ;
  865.   Data->MonitorParms.Active = FALSE ;
  866.   DosWaitThread ( &Data->MonitorTID, DCWW_WAIT ) ;
  867.  
  868.   DosResumeThread ( Data->IdleLoopTID ) ;
  869.   Data->IdleLoopParms.Active = FALSE ;
  870.   DosWaitThread ( &Data->IdleLoopTID, DCWW_WAIT ) ;
  871.  
  872.  /***************************************************************************
  873.   * Release the instance memory.                                            *
  874.   ***************************************************************************/
  875.  
  876.   free ( Data ) ;
  877.  
  878.  /***************************************************************************
  879.   * We're done.                                                             *
  880.   ***************************************************************************/
  881.  
  882.   return ( MRFROMSHORT ( 0 ) ) ;
  883. }
  884.  
  885. /****************************************************************************
  886.  *                                                                          *
  887.  *      Process window resize message.                                      *
  888.  *                                                                          *
  889.  ****************************************************************************/
  890.  
  891. STATIC MRESULT APIENTRY Size
  892. (
  893.   HWND hwnd,
  894.   USHORT msg,
  895.   MPARAM mp1,
  896.   MPARAM mp2
  897. )
  898. {
  899.  /***************************************************************************
  900.   * Find the instance data.                                                 *
  901.   ***************************************************************************/
  902.  
  903.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  904.  
  905.  /***************************************************************************
  906.   * Find out the window's new position and size.                            *
  907.   ***************************************************************************/
  908.  
  909.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  910.  
  911.   SWP Position ;
  912.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  913.  
  914.   if ( NOT ( Position.fl & SWP_MINIMIZE )
  915.     AND NOT ( Position.fl & SWP_MAXIMIZE ) )
  916.   {
  917.     Data->Profile.Position.x = Position.x ;
  918.     Data->Profile.Position.y = Position.y ;
  919.  
  920.     Data->Profile.Position.cx = Position.cx ;
  921.     Data->Profile.Position.cy = Position.cy ;
  922.   }
  923.  
  924.  /***************************************************************************
  925.   * If hiding the controls . . .                                            *
  926.   ***************************************************************************/
  927.  
  928.   if ( Data->Profile.HideControls )
  929.   {
  930.  
  931.    /*************************************************************************
  932.     * If changing to or from minimized state . . .                          *
  933.     *************************************************************************/
  934.  
  935.     if ( ( Position.fl & SWP_MINIMIZE ) != ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  936.     {
  937.  
  938.      /***********************************************************************
  939.       * Hide the controls if no longer minimized.                           *
  940.       ***********************************************************************/
  941.  
  942.       HideControls
  943.       (
  944.         NOT ( Position.fl & SWP_MINIMIZE ),
  945.         hwndFrame,
  946.         Data->hwndSysMenu,
  947.         Data->hwndTitleBar,
  948.         Data->hwndMinMax
  949.       ) ;
  950.     }
  951.   }
  952.  
  953.   Data->Profile.Position.fl = Position.fl ;
  954.  
  955.  /***************************************************************************
  956.   * We're done.                                                             *
  957.   ***************************************************************************/
  958.  
  959.   return ( 0 ) ;
  960. }
  961.  
  962. /****************************************************************************
  963.  *                                                                          *
  964.  *      Process SAVE APPLICATION message.                                   *
  965.  *                                                                          *
  966.  ****************************************************************************/
  967.  
  968. STATIC MRESULT APIENTRY SaveApplication
  969. (
  970.   HWND hwnd,
  971.   USHORT msg,
  972.   MPARAM mp1,
  973.   MPARAM mp2
  974. )
  975. {
  976.  /***************************************************************************
  977.   * Find the instance data.                                                 *
  978.   ***************************************************************************/
  979.  
  980.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  981.  
  982.  /***************************************************************************
  983.   * Call function to put all profile data out to the system.                *
  984.   ***************************************************************************/
  985.  
  986.   PutProfile ( Data->ProfileHandle, &Data->Profile ) ;
  987.  
  988.  /***************************************************************************
  989.   * We're done.  Let the system complete default processing.                *
  990.   ***************************************************************************/
  991.  
  992.   return ( WinDefWindowProc ( hwnd, WM_SAVEAPPLICATION, 0, 0 ) ) ;
  993. }
  994.  
  995. /****************************************************************************
  996.  *                                                                          *
  997.  *      Repaint entire window.                                              *
  998.  *                                                                          *
  999.  ****************************************************************************/
  1000.  
  1001. STATIC MRESULT APIENTRY Paint
  1002. (
  1003.   HWND hwnd,
  1004.   USHORT msg,
  1005.   MPARAM mp1,
  1006.   MPARAM mp2
  1007. )
  1008. {
  1009.  /***************************************************************************
  1010.   * Find the instance data.                                                 *
  1011.   ***************************************************************************/
  1012.  
  1013.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1014.  
  1015.  /***************************************************************************
  1016.   * Get presentation space and make it use RGB colors.                      *
  1017.   ***************************************************************************/
  1018.  
  1019.   HPS hPS = WinBeginPaint ( hwnd, HPS(NULL), PRECTL(NULL) ) ;
  1020.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, PLONG(NULL) ) ;
  1021.  
  1022.  /***************************************************************************
  1023.   * Clear the window.                                                       *
  1024.   ***************************************************************************/
  1025.  
  1026.   RECTL Rectangle ;
  1027.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  1028.  
  1029.   GpiMove ( hPS, (PPOINTL) &Rectangle.xLeft ) ;
  1030.   GpiSetColor ( hPS, Data->Profile.BackColor ) ;
  1031.   GpiBox ( hPS, DRO_FILL, (PPOINTL) &Rectangle.xRight, 0L, 0L ) ;
  1032.  
  1033.  /***************************************************************************
  1034.   * Release presentation space.                                             *
  1035.   ***************************************************************************/
  1036.  
  1037.   WinEndPaint ( hPS ) ;
  1038.  
  1039.  /***************************************************************************
  1040.   * Update the window and return.                                           *
  1041.   ***************************************************************************/
  1042.  
  1043.   UpdateWindow ( hwnd, Data, TRUE ) ;
  1044.  
  1045.   return ( 0 ) ;
  1046. }
  1047.  
  1048. /****************************************************************************
  1049.  *                                                                          *
  1050.  *      Process commands received by Main Window                            *
  1051.  *                                                                          *
  1052.  ****************************************************************************/
  1053.  
  1054. STATIC MRESULT APIENTRY Command
  1055. (
  1056.   HWND hwnd,
  1057.   USHORT msg,
  1058.   MPARAM mp1,
  1059.   MPARAM mp2
  1060. )
  1061. {
  1062.  /***************************************************************************
  1063.   * Dispatch all other commands through the method table.                   *
  1064.   ***************************************************************************/
  1065.  
  1066.   static METHOD Methods [] =
  1067.   {
  1068.     { IDM_SAVE_APPLICATION, SaveApplication },
  1069.     { IDM_RESET_DEFAULTS,   ResetDefaults   },
  1070.     { IDM_HIDE_CONTROLS,    HideControlsCmd },
  1071.     { IDM_CONFIGURE,        Configure       },
  1072.     { IDM_EXIT,             Exit            },
  1073.     { IDM_ABOUT,            About           },
  1074.   } ;
  1075.  
  1076.   return ( DispatchMessage ( hwnd, SHORT1FROMMP(mp1), mp1, mp2, Methods, sizeof(Methods)/sizeof(Methods[0]), PFNWP(NULL) ) ) ;
  1077. }
  1078.  
  1079. /****************************************************************************
  1080.  *                                                                          *
  1081.  *      Process Reset Defaults menu command.                                *
  1082.  *                                                                          *
  1083.  ****************************************************************************/
  1084.  
  1085. STATIC MRESULT APIENTRY ResetDefaults
  1086.   HWND hwnd, 
  1087.   USHORT msg, 
  1088.   MPARAM mp1, 
  1089.   MPARAM mp2
  1090. )
  1091. {
  1092.  /***************************************************************************
  1093.   * Find the instance data.                                                 *
  1094.   ***************************************************************************/
  1095.  
  1096.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1097.  
  1098.  /***************************************************************************
  1099.   * Reset all profile data for this program.                                *
  1100.   ***************************************************************************/
  1101.  
  1102.   PrfWriteProfileData ( Data->ProfileHandle, PSZ(PROGRAM_NAME), PSZ(NULL), PSZ(NULL), 0 ) ;
  1103.  
  1104.  /***************************************************************************
  1105.   * Reset the program's presentation parameters.                            *
  1106.   ***************************************************************************/
  1107.  
  1108.   WinRemovePresParam ( hwnd, PP_FONTNAMESIZE ) ;
  1109.   WinRemovePresParam ( hwnd, PP_FOREGROUNDCOLOR ) ;
  1110.   WinRemovePresParam ( hwnd, PP_BACKGROUNDCOLOR ) ;
  1111.  
  1112.  /***************************************************************************
  1113.   * Done.                                                                   *
  1114.   ***************************************************************************/
  1115.  
  1116.   return ( MRFROMSHORT ( 0 ) ) ;
  1117. }
  1118.  
  1119. /****************************************************************************
  1120.  *                                                                          *
  1121.  *      Process Hide Controls menu command.                                 *
  1122.  *                                                                          *
  1123.  ****************************************************************************/
  1124.  
  1125. STATIC MRESULT APIENTRY HideControlsCmd
  1126.   HWND hwnd, 
  1127.   USHORT msg, 
  1128.   MPARAM mp1, 
  1129.   MPARAM mp2
  1130. )
  1131. {
  1132.  /***************************************************************************
  1133.   * Find the instance data.                                                 *
  1134.   ***************************************************************************/
  1135.  
  1136.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1137.  
  1138.  /***************************************************************************
  1139.   * Toggle the Hide Controls setting.                                       *
  1140.   ***************************************************************************/
  1141.  
  1142.   Data->Profile.HideControls = Data->Profile.HideControls ? FALSE : TRUE ;
  1143.   Data->Profile.fHideControls = TRUE ;
  1144.  
  1145.  /***************************************************************************
  1146.   * Get the frame handle.                                                   *
  1147.   ***************************************************************************/
  1148.  
  1149.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  1150.  
  1151.  /***************************************************************************
  1152.   * If controls aren't hidden yet, update the menu check-mark.              *
  1153.   ***************************************************************************/
  1154.  
  1155.   if ( Data->Profile.HideControls )
  1156.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1157.  
  1158.  /***************************************************************************
  1159.   * If not minimized right now, hide or reveal the controls.                *
  1160.   ***************************************************************************/
  1161.  
  1162.   if ( NOT ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  1163.   {
  1164.     HideControls
  1165.     (
  1166.       Data->Profile.HideControls,
  1167.       hwndFrame,
  1168.       Data->hwndSysMenu,
  1169.       Data->hwndTitleBar,
  1170.       Data->hwndMinMax
  1171.     ) ;
  1172.   }
  1173.  
  1174.  /***************************************************************************
  1175.   * If controls are no longer hidden, update the menu check-mark.           *
  1176.   ***************************************************************************/
  1177.  
  1178.   if ( NOT Data->Profile.HideControls )
  1179.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1180.  
  1181.  /***************************************************************************
  1182.   * Done.                                                                   *
  1183.   ***************************************************************************/
  1184.  
  1185.   return ( MRFROMSHORT ( 0 ) ) ;
  1186. }
  1187.  
  1188. /****************************************************************************
  1189.  *                                                                          *
  1190.  *      Process Configure command.                                          *
  1191.  *                                                                          *
  1192.  ****************************************************************************/
  1193.  
  1194. STATIC MRESULT APIENTRY Configure
  1195.   HWND hwnd, 
  1196.   USHORT msg, 
  1197.   MPARAM mp1, 
  1198.   MPARAM mp2
  1199. )
  1200. {
  1201.  /***************************************************************************
  1202.   * Find the instance data.                                                 *
  1203.   ***************************************************************************/
  1204.  
  1205.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1206.  
  1207.  /***************************************************************************
  1208.   * Invoke the Configure dialog.  If cancelled, just return.                *
  1209.   ***************************************************************************/
  1210.  
  1211.   CONFIG_PARMS Parms ;
  1212.   Parms.id            = IDD_CONFIGURE ;
  1213.   Parms.hwndHelp      = WinQueryHelpInstance ( hwnd ) ;
  1214.   Parms.HideControls  = Data->Profile.HideControls ;
  1215.   Parms.Float         = Data->Profile.Float ;
  1216.   Parms.Animate       = Data->Profile.Animate ;
  1217.   Parms.TimerInterval = Data->Profile.TimerInterval ;
  1218.  
  1219.   Parms.ItemCount     = Data->Profile.ItemCount ;
  1220.  
  1221.   PSZ  ItemNames [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  1222.   BOOL ItemFlags [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  1223.   for ( int i=0; i<Data->Profile.ItemCount; i++ )
  1224.   {
  1225.     ItemNames[i] = Data->Profile.Items[i]->QueryOption () ;
  1226.     ItemFlags[i] = Data->Profile.Items[i]->QueryFlag () ;
  1227.   }
  1228.   Parms.ItemNames = ItemNames ;
  1229.   Parms.ItemFlags = ItemFlags ;
  1230.  
  1231.   if ( WinDlgBox ( HWND_DESKTOP, hwnd, PFNWP(ConfigureProcessor),
  1232.     Data->Library, IDD_CONFIGURE, &Parms ) == FALSE )
  1233.   {
  1234.     return ( MRFROMSHORT ( 0 ) ) ;
  1235.   }
  1236.  
  1237.  /***************************************************************************
  1238.   * Save the new timer interval.                                            *
  1239.   ***************************************************************************/
  1240.  
  1241.   Data->Profile.fTimerInterval = TRUE ;
  1242.   Data->Profile.TimerInterval = Parms.TimerInterval ;
  1243.  
  1244.  /***************************************************************************
  1245.   * Save the float-to-top flag.                                             *
  1246.   ***************************************************************************/
  1247.  
  1248.   Data->Profile.fFloat = TRUE ;
  1249.   Data->Profile.Float = Parms.Float ;
  1250.  
  1251.  /***************************************************************************
  1252.   * Save the window animate flag.                                           *
  1253.   ***************************************************************************/
  1254.  
  1255.   Data->Profile.fAnimate = TRUE ;
  1256.   Data->Profile.Animate = Parms.Animate ;
  1257.  
  1258.  /***************************************************************************
  1259.   * Save the hide controls flag, and adjust the window if it changed.       *
  1260.   ***************************************************************************/
  1261.  
  1262.   Data->Profile.fHideControls = TRUE ;
  1263.   if ( Data->Profile.HideControls != Parms.HideControls )
  1264.   {
  1265.     HWND FrameWindow = WinQueryWindow ( hwnd, QW_PARENT ) ;
  1266.     Data->Profile.HideControls = Parms.HideControls ;
  1267.     if ( Data->Profile.HideControls )
  1268.       CheckMenuItem ( FrameWindow, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1269.     if ( NOT ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  1270.     {
  1271.       HideControls
  1272.       (
  1273.         Data->Profile.HideControls,
  1274.         FrameWindow,
  1275.         Data->hwndSysMenu,
  1276.         Data->hwndTitleBar,
  1277.         Data->hwndMinMax
  1278.       ) ;
  1279.     }
  1280.     if ( NOT Data->Profile.HideControls )
  1281.       CheckMenuItem ( FrameWindow, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1282.   }
  1283.  
  1284.  /***************************************************************************
  1285.   * Determine if the display item list has changed.  If not, return.        *
  1286.   ***************************************************************************/
  1287.  
  1288.   BOOL ItemsChanged = FALSE ;
  1289.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  1290.   {
  1291.     if ( ItemFlags[i] != Data->Profile.Items[i]->QueryFlag() )
  1292.     {
  1293.       ItemsChanged = TRUE ;
  1294.       break ;
  1295.     }
  1296.   }
  1297.  
  1298.   if ( NOT ItemsChanged )
  1299.   {
  1300.     return ( MRFROMSHORT ( 0 ) ) ;
  1301.   }
  1302.  
  1303.  /***************************************************************************
  1304.   * If CPU load monitoring has changed, start/stop the monitoring thread.   *
  1305.   ***************************************************************************/
  1306.  
  1307.   if ( ItemFlags[ITEM_CPULOAD] != Data->Profile.Items[ITEM_CPULOAD]->QueryFlag() )
  1308.   {
  1309.     if ( ItemFlags[ITEM_CPULOAD] )
  1310.       DosResumeThread ( Data->IdleLoopTID ) ;
  1311.     else
  1312.       DosSuspendThread ( Data->IdleLoopTID ) ;
  1313.   }
  1314.  
  1315.  /***************************************************************************
  1316.   * Save the new item flags.                                                *
  1317.   ***************************************************************************/
  1318.  
  1319.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  1320.   {
  1321.     if ( ItemFlags[i] )
  1322.       Data->Profile.Items[i]->SetFlag ( ) ;
  1323.     else
  1324.       Data->Profile.Items[i]->ResetFlag ( ) ;
  1325.   }
  1326.  
  1327.  /***************************************************************************
  1328.   * Resize the display window.                                              *
  1329.   ***************************************************************************/
  1330.  
  1331.   ResizeWindow ( hwnd, &Data->Profile ) ;
  1332.  
  1333.  /***************************************************************************
  1334.   * Done.                                                                   *
  1335.   ***************************************************************************/
  1336.  
  1337.   return ( MRFROMSHORT ( 0 ) ) ;
  1338. }
  1339.  
  1340. /****************************************************************************
  1341.  *                                                                          *
  1342.  *      Process About menu command.                                         *
  1343.  *                                                                          *
  1344.  ****************************************************************************/
  1345.  
  1346. STATIC MRESULT APIENTRY About
  1347.   HWND hwnd, 
  1348.   USHORT msg, 
  1349.   MPARAM mp1, 
  1350.   MPARAM mp2
  1351. )
  1352. {
  1353.  /***************************************************************************
  1354.   * Find the instance data.                                                 *
  1355.   ***************************************************************************/
  1356.  
  1357.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1358.  
  1359.  /***************************************************************************
  1360.   * Invoke the About dialog.                                                *
  1361.   ***************************************************************************/
  1362.  
  1363.   ABOUT_PARMS Parms ;
  1364.   Parms.id = IDD_ABOUT ;
  1365.   Parms.hwndHelp = WinQueryHelpInstance ( hwnd ) ;
  1366.  
  1367.   WinDlgBox ( HWND_DESKTOP, hwnd, PFNWP(AboutProcessor),
  1368.     Data->Library, IDD_ABOUT, &Parms ) ;
  1369.  
  1370.  /***************************************************************************
  1371.   * Done.                                                                   *
  1372.   ***************************************************************************/
  1373.  
  1374.   return ( MRFROMSHORT ( 0 ) ) ;
  1375. }
  1376.  
  1377. /****************************************************************************
  1378.  *                                                                          *
  1379.  *      Process Mouse Button being pressed.                                 *
  1380.  *                                                                          *
  1381.  ****************************************************************************/
  1382.  
  1383. STATIC MRESULT APIENTRY ButtonDown
  1384. (
  1385.   HWND hwnd,
  1386.   USHORT msg,
  1387.   MPARAM mp1,
  1388.   MPARAM mp2
  1389. )
  1390. {
  1391.  /***************************************************************************
  1392.   * Find the instance data.                                                 *
  1393.   ***************************************************************************/
  1394.  
  1395.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1396.  
  1397.  /***************************************************************************
  1398.   * Determine the new window position.                                      *
  1399.   ***************************************************************************/
  1400.  
  1401.   TRACKINFO TrackInfo ;
  1402.   memset ( &TrackInfo, 0, sizeof(TrackInfo) ) ;
  1403.  
  1404.   TrackInfo.cxBorder = 1 ;
  1405.   TrackInfo.cyBorder = 1 ;
  1406.   TrackInfo.cxGrid = 1 ;
  1407.   TrackInfo.cyGrid = 1 ;
  1408.   TrackInfo.cxKeyboard = 8 ;
  1409.   TrackInfo.cyKeyboard = 8 ;
  1410.  
  1411.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  1412.  
  1413.   SWP Position ;
  1414.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  1415.   TrackInfo.rclTrack.xLeft   = Position.x ;
  1416.   TrackInfo.rclTrack.xRight  = Position.x + Position.cx ;
  1417.   TrackInfo.rclTrack.yBottom = Position.y ;
  1418.   TrackInfo.rclTrack.yTop    = Position.y + Position.cy ;
  1419.  
  1420.   WinQueryWindowPos ( HWND_DESKTOP, &Position ) ;
  1421.   TrackInfo.rclBoundary.xLeft   = Position.x ;
  1422.   TrackInfo.rclBoundary.xRight  = Position.x + Position.cx ;
  1423.   TrackInfo.rclBoundary.yBottom = Position.y ;
  1424.   TrackInfo.rclBoundary.yTop    = Position.y + Position.cy ;
  1425.  
  1426.   TrackInfo.ptlMinTrackSize.x = 0 ;
  1427.   TrackInfo.ptlMinTrackSize.y = 0 ;
  1428.   TrackInfo.ptlMaxTrackSize.x = Position.cx ;
  1429.   TrackInfo.ptlMaxTrackSize.y = Position.cy ;
  1430.  
  1431.   TrackInfo.fs = TF_MOVE | TF_STANDARD | TF_ALLINBOUNDARY ;
  1432.  
  1433.   if ( WinTrackRect ( HWND_DESKTOP, HPS(NULL), &TrackInfo ) )
  1434.   {
  1435.     WinSetWindowPos ( hwndFrame, 0,
  1436.       (SHORT) TrackInfo.rclTrack.xLeft,
  1437.       (SHORT) TrackInfo.rclTrack.yBottom,
  1438.       0, 0, SWP_MOVE ) ;
  1439.   }
  1440.  
  1441.  /***************************************************************************
  1442.   * Return through the default processor, letting window activation         *
  1443.   *   and other system functions occur.                                     *
  1444.   ***************************************************************************/
  1445.  
  1446.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1447. }
  1448.  
  1449. /****************************************************************************
  1450.  *                                                                          *
  1451.  *      Process Mouse Button having been double-clicked.                    *
  1452.  *                                                                          *
  1453.  ****************************************************************************/
  1454.  
  1455. STATIC MRESULT APIENTRY ButtonDblClick
  1456. (
  1457.   HWND hwnd,
  1458.   USHORT msg,
  1459.   MPARAM mp1,
  1460.   MPARAM mp2
  1461. )
  1462. {
  1463.  /***************************************************************************
  1464.   * Send message to self to stop hiding the controls.                       *
  1465.   ***************************************************************************/
  1466.  
  1467.   WinPostMsg ( hwnd, WM_COMMAND,
  1468.     MPFROM2SHORT ( IDM_HIDE_CONTROLS, 0 ),
  1469.     MPFROM2SHORT ( CMDSRC_OTHER, TRUE ) ) ;
  1470.  
  1471.  /***************************************************************************
  1472.   * Return through the default processor, letting window activation         *
  1473.   *   and other system functions occur.                                     *
  1474.   ***************************************************************************/
  1475.  
  1476.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1477. }
  1478.  
  1479. /****************************************************************************
  1480.  *                                                                          *
  1481.  *      Process Presentation Parameter Changed notification.                *
  1482.  *                                                                          *
  1483.  ****************************************************************************/
  1484.  
  1485. STATIC MRESULT APIENTRY PresParamChanged
  1486. (
  1487.   HWND hwnd,
  1488.   USHORT msg,
  1489.   MPARAM mp1,
  1490.   MPARAM mp2
  1491. )
  1492. {
  1493.  /***************************************************************************
  1494.   * Find the instance data.                                                 *
  1495.   ***************************************************************************/
  1496.  
  1497.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1498.  
  1499.  /***************************************************************************
  1500.   * Get the presentation parameter that changed.                            *
  1501.   ***************************************************************************/
  1502.  
  1503.   switch ( LONGFROMMP(mp1) )
  1504.   {
  1505.  
  1506.    /*************************************************************************
  1507.     * If font, note the fact that we now have a font to be saved as         *
  1508.     *   part of the configuration.  Get the font metrics and resize         *
  1509.     *   the window appropriately.                                           *
  1510.     *************************************************************************/
  1511.  
  1512.     case PP_FONTNAMESIZE:
  1513.     {
  1514.       ULONG ppid ;
  1515.       if ( WinQueryPresParam ( hwnd, PP_FONTNAMESIZE, 0, &ppid,
  1516.         sizeof(Data->Profile.FontNameSize), &Data->Profile.FontNameSize,
  1517.         0 ) )
  1518.       {
  1519.         Data->Profile.fFontNameSize = TRUE ;
  1520.       }
  1521.       else
  1522.       {
  1523.         strcpy ( PCHAR(Data->Profile.FontNameSize), "" ) ;
  1524.         Data->Profile.fFontNameSize = FALSE ;
  1525.         PrfWriteProfileData ( Data->ProfileHandle, PSZ(PROGRAM_NAME), PSZ("FontNameSize"), NULL, 0 ) ;
  1526.       }
  1527.  
  1528.       HPS hPS = WinGetPS ( hwnd ) ;
  1529.       RECTL Rectangle ;
  1530.       WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  1531.       WinDrawText ( hPS, 1, PSZ(" "), &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  1532.       Data->Width  = Rectangle.xRight - Rectangle.xLeft ;
  1533.       Data->Height = Rectangle.yTop - Rectangle.yBottom ;
  1534.       WinReleasePS ( hPS ) ;
  1535.       ResizeWindow ( hwnd, &Data->Profile ) ;
  1536.       break ;
  1537.     }
  1538.  
  1539.    /*************************************************************************
  1540.     * If background color, note the fact and repaint the window.            *
  1541.     *************************************************************************/
  1542.  
  1543.     case PP_BACKGROUNDCOLOR:
  1544.     {
  1545.       ULONG ppid ;
  1546.       if ( WinQueryPresParam ( hwnd, PP_BACKGROUNDCOLOR, 0, &ppid,
  1547.         sizeof(Data->Profile.BackColor), &Data->Profile.BackColor, 0 ) )
  1548.       {
  1549.         Data->Profile.fBackColor = TRUE ;
  1550.       }
  1551.       else
  1552.       {
  1553.         Data->Profile.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1554.         Data->Profile.fBackColor = FALSE ;
  1555.         PrfWriteProfileData ( Data->ProfileHandle, PSZ(PROGRAM_NAME), PSZ("BackgroundColor"), NULL, 0 ) ;
  1556.       }
  1557.       WinInvalidateRect ( hwnd, PRECTL(NULL), TRUE ) ;
  1558.       break ;
  1559.     }
  1560.  
  1561.    /*************************************************************************
  1562.     * If foreground color, note the fact and repaint the window.            *
  1563.     *************************************************************************/
  1564.  
  1565.     case PP_FOREGROUNDCOLOR:
  1566.     {
  1567.       ULONG ppid ;
  1568.       if ( WinQueryPresParam ( hwnd, PP_FOREGROUNDCOLOR, 0, &ppid,
  1569.         sizeof(Data->Profile.TextColor), &Data->Profile.TextColor, 0 ) )
  1570.       {
  1571.         Data->Profile.fTextColor = TRUE ;
  1572.       }
  1573.       else
  1574.       {
  1575.         Data->Profile.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1576.         Data->Profile.fTextColor = FALSE ;
  1577.         PrfWriteProfileData ( Data->ProfileHandle, PSZ(PROGRAM_NAME), PSZ("ForegroundColor"), NULL, 0 ) ;
  1578.       }
  1579.       WinInvalidateRect ( hwnd, PRECTL(NULL), TRUE ) ;
  1580.       break ;
  1581.     }
  1582.   }
  1583.  
  1584.  /***************************************************************************
  1585.   * Return through the default processor, letting window activation         *
  1586.   *   and other system functions occur.                                     *
  1587.   ***************************************************************************/
  1588.  
  1589.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1590. }
  1591.  
  1592. /****************************************************************************
  1593.  *                                                                          *
  1594.  *      Process System Color Change notification.                           *
  1595.  *                                                                          *
  1596.  ****************************************************************************/
  1597.  
  1598. STATIC MRESULT APIENTRY SysColorChange
  1599. (
  1600.   HWND hwnd,
  1601.   USHORT msg,
  1602.   MPARAM mp1,
  1603.   MPARAM mp2
  1604. )
  1605. {
  1606.  /***************************************************************************
  1607.   * Find the instance data.                                                 *
  1608.   ***************************************************************************/
  1609.  
  1610.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1611.  
  1612.  /***************************************************************************
  1613.   * If we aren't using custom colors, then query for the new defaults.      *
  1614.   ***************************************************************************/
  1615.  
  1616.   if ( NOT Data->Profile.fBackColor )
  1617.   {
  1618.     Data->Profile.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1619.   }
  1620.  
  1621.   if ( NOT Data->Profile.fTextColor )
  1622.   {
  1623.     Data->Profile.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1624.   }
  1625.  
  1626.  /***************************************************************************
  1627.   * Return value must be NULL, according to the documentation.              *
  1628.   ***************************************************************************/
  1629.  
  1630.   return ( MRFROMP ( NULL ) ) ;
  1631. }
  1632.  
  1633. /****************************************************************************
  1634.  *                                                                          *
  1635.  *      Process Query for Keys Help resource id.                            *
  1636.  *                                                                          *
  1637.  ****************************************************************************/
  1638.  
  1639. STATIC MRESULT APIENTRY QueryKeysHelp
  1640. (
  1641.   HWND hwnd,
  1642.   USHORT msg,
  1643.   MPARAM mp1,
  1644.   MPARAM mp2
  1645. )
  1646. {
  1647.  /***************************************************************************
  1648.   * Simply return the ID of the Keys Help panel.                            *
  1649.   ***************************************************************************/
  1650.  
  1651.   return ( (MRESULT) IDM_KEYS_HELP ) ;
  1652. }
  1653.  
  1654. /****************************************************************************
  1655.  *                                                                          *
  1656.  *      Process Help Manager Error                                          *
  1657.  *                                                                          *
  1658.  ****************************************************************************/
  1659.  
  1660. STATIC MRESULT APIENTRY HelpError
  1661.   HWND hwnd, 
  1662.   USHORT msg, 
  1663.   MPARAM mp1, 
  1664.   MPARAM mp2
  1665. )
  1666. {
  1667.  /***************************************************************************
  1668.   * Local Declarations                                                      *
  1669.   ***************************************************************************/
  1670.  
  1671.   static struct
  1672.   {
  1673.     ULONG Error ;
  1674.     USHORT StringId ;
  1675.   }
  1676.   HelpErrors [] =
  1677.   {
  1678.     { HMERR_NO_FRAME_WND_IN_CHAIN,     IDS_HMERR_NO_FRAME_WND_IN_CHAIN },
  1679.     { HMERR_INVALID_ASSOC_APP_WND,     IDS_HMERR_INVALID_ASSOC_APP_WND },
  1680.     { HMERR_INVALID_ASSOC_HELP_INST,   IDS_HMERR_INVALID_ASSOC_HELP_IN },
  1681.     { HMERR_INVALID_DESTROY_HELP_INST, IDS_HMERR_INVALID_DESTROY_HELP_ },
  1682.     { HMERR_NO_HELP_INST_IN_CHAIN,     IDS_HMERR_NO_HELP_INST_IN_CHAIN },
  1683.     { HMERR_INVALID_HELP_INSTANCE_HDL, IDS_HMERR_INVALID_HELP_INSTANCE },
  1684.     { HMERR_INVALID_QUERY_APP_WND,     IDS_HMERR_INVALID_QUERY_APP_WND },
  1685.     { HMERR_HELP_INST_CALLED_INVALID,  IDS_HMERR_HELP_INST_CALLED_INVA },
  1686.     { HMERR_HELPTABLE_UNDEFINE,        IDS_HMERR_HELPTABLE_UNDEFINE    },
  1687.     { HMERR_HELP_INSTANCE_UNDEFINE,    IDS_HMERR_HELP_INSTANCE_UNDEFIN },
  1688.     { HMERR_HELPITEM_NOT_FOUND,        IDS_HMERR_HELPITEM_NOT_FOUND    },
  1689.     { HMERR_INVALID_HELPSUBITEM_SIZE,  IDS_HMERR_INVALID_HELPSUBITEM_S },
  1690.     { HMERR_HELPSUBITEM_NOT_FOUND,     IDS_HMERR_HELPSUBITEM_NOT_FOUND },
  1691.     { HMERR_INDEX_NOT_FOUND,           IDS_HMERR_INDEX_NOT_FOUND       },
  1692.     { HMERR_CONTENT_NOT_FOUND,         IDS_HMERR_CONTENT_NOT_FOUND     },
  1693.     { HMERR_OPEN_LIB_FILE,             IDS_HMERR_OPEN_LIB_FILE         },
  1694.     { HMERR_READ_LIB_FILE,             IDS_HMERR_READ_LIB_FILE         },
  1695.     { HMERR_CLOSE_LIB_FILE,            IDS_HMERR_CLOSE_LIB_FILE        },
  1696.     { HMERR_INVALID_LIB_FILE,          IDS_HMERR_INVALID_LIB_FILE      },
  1697.     { HMERR_NO_MEMORY,                 IDS_HMERR_NO_MEMORY             },
  1698.     { HMERR_ALLOCATE_SEGMENT,          IDS_HMERR_ALLOCATE_SEGMENT      },
  1699.     { HMERR_FREE_MEMORY,               IDS_HMERR_FREE_MEMORY           },
  1700.     { HMERR_PANEL_NOT_FOUND,           IDS_HMERR_PANEL_NOT_FOUND       },
  1701.     { HMERR_DATABASE_NOT_OPEN,         IDS_HMERR_DATABASE_NOT_OPEN     },
  1702.     { 0,                               IDS_HMERR_UNKNOWN               }
  1703.   } ;
  1704.  
  1705.   ULONG ErrorCode = (ULONG) LONGFROMMP ( mp1 ) ;
  1706.  
  1707.  /***************************************************************************
  1708.   * Find the instance data.                                                 *
  1709.   ***************************************************************************/
  1710.  
  1711.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1712.  
  1713.  /***************************************************************************
  1714.   * Find the error code in the message table.                               *
  1715.   ***************************************************************************/
  1716.  
  1717.   int Index = 0 ;
  1718.   while ( HelpErrors[Index].Error
  1719.     AND ( HelpErrors[Index].Error != ErrorCode ) )
  1720.   {
  1721.     Index ++ ;
  1722.   }
  1723.  
  1724.  /***************************************************************************
  1725.   * Get the message texts.                                                  *
  1726.   ***************************************************************************/
  1727.  
  1728.   ResourceString Title ( Data->Library, IDS_HMERR ) ;
  1729.  
  1730.   ResourceString Message ( Data->Library, HelpErrors[Index].StringId ) ;
  1731.  
  1732.  /***************************************************************************
  1733.   * Display the error message.                                              *
  1734.   ***************************************************************************/
  1735.  
  1736.   WinMessageBox
  1737.   (
  1738.     HWND_DESKTOP,
  1739.     hwnd,
  1740.     PSZ(Message),
  1741.     PSZ(Title),
  1742.     0,
  1743.     MB_OK | MB_WARNING
  1744.   ) ;
  1745.  
  1746.  /***************************************************************************
  1747.   * Return zero, indicating that the message was processed.                 *
  1748.   ***************************************************************************/
  1749.  
  1750.   return ( MRFROMSHORT ( 0 ) ) ;
  1751. }
  1752.  
  1753. /****************************************************************************
  1754.  *                                                                          *
  1755.  *      Process "Extended Help Undefined" notification                      *
  1756.  *                                                                          *
  1757.  ****************************************************************************/
  1758.  
  1759. STATIC MRESULT APIENTRY ExtHelpUndefined
  1760.   HWND hwnd, 
  1761.   USHORT msg, 
  1762.   MPARAM mp1, 
  1763.   MPARAM mp2
  1764. )
  1765. {
  1766.  /***************************************************************************
  1767.   * Find the instance data.                                                 *
  1768.   ***************************************************************************/
  1769.  
  1770.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1771.  
  1772.  /***************************************************************************
  1773.   * Get the message texts.                                                  *
  1774.   ***************************************************************************/
  1775.  
  1776.   ResourceString Title ( Data->Library, IDS_HMERR ) ;
  1777.  
  1778.   ResourceString Message ( Data->Library, IDS_HMERR_EXTHELPUNDEFINED ) ;
  1779.  
  1780.  /***************************************************************************
  1781.   * Display the error message.                                              *
  1782.   ***************************************************************************/
  1783.  
  1784.   WinMessageBox
  1785.   (
  1786.     HWND_DESKTOP,
  1787.     hwnd,
  1788.     PSZ(Message),
  1789.     PSZ(Title),
  1790.     0,
  1791.     MB_OK | MB_WARNING
  1792.   ) ;
  1793.  
  1794.  /***************************************************************************
  1795.   * Return zero, indicating that the message was processed.                 *
  1796.   ***************************************************************************/
  1797.  
  1798.   return ( MRFROMSHORT ( 0 ) ) ;
  1799. }
  1800.  
  1801. /****************************************************************************
  1802.  *                                                                          *
  1803.  *      Process "Help Subitem Not Found" notification                       *
  1804.  *                                                                          *
  1805.  ****************************************************************************/
  1806.  
  1807. STATIC MRESULT APIENTRY HelpSubitemNotFound
  1808.   HWND hwnd, 
  1809.   USHORT msg, 
  1810.   MPARAM mp1, 
  1811.   MPARAM mp2
  1812. )
  1813. {
  1814.  /***************************************************************************
  1815.   * Find the instance data.                                                 *
  1816.   ***************************************************************************/
  1817.  
  1818.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1819.  
  1820.  /***************************************************************************
  1821.   * Get the title text.                                                     *
  1822.   ***************************************************************************/
  1823.  
  1824.   ResourceString Title ( Data->Library, IDS_HMERR ) ;
  1825.  
  1826.  /***************************************************************************
  1827.   * Format the error message.                                               *
  1828.   ***************************************************************************/
  1829.  
  1830.   USHORT Topic = (USHORT) SHORT1FROMMP ( mp2 ) ;
  1831.   USHORT Subtopic = (USHORT) SHORT2FROMMP ( mp2 ) ;
  1832.  
  1833.   ResourceString Frame   ( Data->Library, IDS_HELPMODE_FRAME ) ;
  1834.   ResourceString Menu    ( Data->Library, IDS_HELPMODE_MENU ) ;
  1835.   ResourceString Window  ( Data->Library, IDS_HELPMODE_WINDOW ) ;
  1836.   ResourceString Unknown ( Data->Library, IDS_HELPMODE_UNKNOWN ) ;
  1837.  
  1838.   PBYTE Mode ;
  1839.   switch ( SHORT1FROMMP ( mp1 ) )
  1840.   {
  1841.     case HLPM_FRAME:
  1842.       Mode = PSZ(Frame) ;
  1843.       break ;
  1844.  
  1845.     case HLPM_MENU:
  1846.       Mode = PSZ(Menu) ;
  1847.       break ;
  1848.  
  1849.     case HLPM_WINDOW:
  1850.       Mode = PSZ(Window) ;
  1851.       break ;
  1852.  
  1853.     default:
  1854.       Mode = PSZ(Unknown) ;
  1855.   }
  1856.  
  1857.   ResourceString Format ( Data->Library, IDS_HELPSUBITEMNOTFOUND ) ;
  1858.  
  1859.   BYTE Message [200] ;
  1860.   sprintf ( PCHAR(Message), PCHAR(Format), Mode, Topic, Subtopic ) ;
  1861.  
  1862.  /***************************************************************************
  1863.   * Display the error message.                                              *
  1864.   ***************************************************************************/
  1865.  
  1866.   WinMessageBox
  1867.   (
  1868.     HWND_DESKTOP,
  1869.     hwnd,
  1870.     Message,
  1871.     PSZ(Title),
  1872.     0,
  1873.     MB_OK | MB_WARNING
  1874.   ) ;
  1875.  
  1876.  /***************************************************************************
  1877.   * Return zero, indicating that the message was processed.                 *
  1878.   ***************************************************************************/
  1879.  
  1880.   return ( MRFROMSHORT ( 0 ) ) ;
  1881. }
  1882.  
  1883. /****************************************************************************
  1884.  *                                                                          *
  1885.  *      Process Refresh message.                                            *
  1886.  *                                                                          *
  1887.  ****************************************************************************/
  1888.  
  1889. STATIC MRESULT APIENTRY Refresh
  1890.   HWND hwnd, 
  1891.   USHORT msg, 
  1892.   MPARAM mp1, 
  1893.   MPARAM mp2
  1894. )
  1895. {
  1896.  /***************************************************************************
  1897.   * Find the instance data.                                                 *
  1898.   ***************************************************************************/
  1899.  
  1900.   PDATA Data = PDATA ( WinQueryWindowPtr ( hwnd, QWL_USER ) ) ;
  1901.  
  1902.  /***************************************************************************
  1903.   * If we're supposed to float the window, do so here.                      *
  1904.   ***************************************************************************/
  1905.  
  1906.   if ( Data->Profile.Float )
  1907.     WinSetWindowPos ( WinQueryWindow(hwnd,QW_PARENT), HWND_TOP, 0, 0, 0, 0, SWP_ZORDER ) ;
  1908.  
  1909.  /***************************************************************************
  1910.   * Save the idle counter.                                                  *
  1911.   ***************************************************************************/
  1912.  
  1913.   Data->Profile.IdleCount = LONGFROMMP ( mp1 ) ;
  1914.  
  1915.  /***************************************************************************
  1916.   * Determine if drive mask has changed.                                    *
  1917.   ***************************************************************************/
  1918.  
  1919.   ULONG Drive ;
  1920.   ULONG Drives ;
  1921.   DosQueryCurrentDisk ( &Drive, &Drives ) ;
  1922.  
  1923.   if ( Drives != Data->Drives )
  1924.   {
  1925.    /*************************************************************************
  1926.     * It has.  First save the display options.                              *
  1927.     *************************************************************************/
  1928.  
  1929.     SaveApplication ( hwnd, WM_SAVEAPPLICATION, 0, 0 ) ;
  1930.  
  1931.    /*************************************************************************
  1932.     * Next, update the drive item list.                                     *
  1933.     *************************************************************************/
  1934.  
  1935.     UpdateDriveList ( Data->Anchor, Data->Library, Data->ProfileHandle, 
  1936.       &Data->Profile, Data->Drives, Drives ) ;
  1937.  
  1938.    /*************************************************************************
  1939.     * If the controls are hidden, hide the whole window and reveal the      *
  1940.     *   controls.  Otherwise the menu wouldn't get updated correctly.       *
  1941.     *************************************************************************/
  1942.  
  1943.     if ( Data->Profile.HideControls )
  1944.     {
  1945.       WinShowWindow ( WinQueryWindow(hwnd,QW_PARENT), FALSE ) ;
  1946.       HideControls
  1947.       (
  1948.         FALSE,
  1949.         WinQueryWindow ( hwnd, QW_PARENT ),
  1950.         Data->hwndSysMenu,
  1951.         Data->hwndTitleBar,
  1952.         Data->hwndMinMax
  1953.       ) ;
  1954.     }
  1955.  
  1956.    /*************************************************************************
  1957.     * If the controls were supposed to be hidden, hide them once more and   *
  1958.     *   show the window to the world again.                                 *
  1959.     *************************************************************************/
  1960.  
  1961.     if ( Data->Profile.HideControls )
  1962.     {
  1963.       HideControls
  1964.       (
  1965.         TRUE,
  1966.         WinQueryWindow ( hwnd, QW_PARENT ),
  1967.         Data->hwndSysMenu,
  1968.         Data->hwndTitleBar,
  1969.         Data->hwndMinMax
  1970.       ) ;
  1971.       WinShowWindow ( WinQueryWindow(hwnd,QW_PARENT), TRUE ) ;
  1972.     }
  1973.  
  1974.    /*************************************************************************
  1975.     * Save the updated drive mask.                                          *
  1976.     *************************************************************************/
  1977.  
  1978.     Data->Drives = Drives ;
  1979.  
  1980.    /*************************************************************************
  1981.     * Resize the window to accommodate the new option list.                 *
  1982.     *************************************************************************/
  1983.  
  1984.     ResizeWindow ( hwnd, &Data->Profile ) ;
  1985.   }
  1986.  
  1987.  /***************************************************************************
  1988.   * Update the statistics.                                                  *
  1989.   ***************************************************************************/
  1990.  
  1991.   UpdateWindow ( hwnd, Data, FALSE ) ;
  1992.  
  1993.  /***************************************************************************
  1994.   * Return zero, indicating that the message was processed.                 *
  1995.   ***************************************************************************/
  1996.  
  1997.   return ( MRFROMSHORT ( 0 ) ) ;
  1998. }
  1999.  
  2000.  
  2001. /****************************************************************************
  2002.  *                                                                          *
  2003.  *                           Get Profile Data                               *
  2004.  *                                                                          *
  2005.  ****************************************************************************/
  2006.  
  2007. STATIC int GetProfile ( HAB Anchor, HMODULE Library, HINI ProfileHandle, PPROFILE Profile )
  2008. {
  2009.  /***************************************************************************
  2010.   * Get the window's current size and position.                             *
  2011.   ***************************************************************************/
  2012.  
  2013.   #pragma pack(2)
  2014.   typedef struct {
  2015.     USHORT Filler ;
  2016.     USHORT fs ;
  2017.     USHORT cy, cx, y, x ;
  2018.     HWND hwndInsertBehind ;
  2019.     HWND hwnd ;
  2020.   } OLDSWP ;
  2021.   #pragma pack()
  2022.  
  2023.   ULONG Size ;
  2024.   memset ( &Profile->Position, 0, sizeof(Profile->Position) ) ;
  2025.   Profile->fPosition = FALSE ;
  2026.   if ( PrfQueryProfileSize ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("Position"), &Size ) )
  2027.   {
  2028.     if ( Size == sizeof(OLDSWP)-sizeof(USHORT) )
  2029.     {
  2030.       OLDSWP OldPosition ;
  2031.       if ( PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("Position"), &OldPosition.fs, &Size ) )
  2032.       {
  2033.         Profile->Position.fl = OldPosition.fs ;
  2034.         Profile->Position.cy = OldPosition.cy ;
  2035.         Profile->Position.cx = OldPosition.cx ;
  2036.         Profile->Position.y = OldPosition.y ;
  2037.         Profile->Position.x = OldPosition.x ;
  2038.         Profile->Position.hwndInsertBehind = OldPosition.hwndInsertBehind ;
  2039.         Profile->Position.hwnd = OldPosition.hwnd ;
  2040.         Profile->fPosition = TRUE ;
  2041.       }
  2042.     }
  2043.     else if ( Size == sizeof(Profile->Position) )
  2044.     {
  2045.       if ( PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("Position"), &Profile->Position, &Size ) )
  2046.       {
  2047.         Profile->fPosition = TRUE ;
  2048.       }
  2049.     }
  2050.   }
  2051.  
  2052.   if ( NOT Profile->fPosition )
  2053.   {
  2054.     if ( ProfileHandle == HINI_USERPROFILE )
  2055.     {
  2056.       return ( 1 ) ;
  2057.     }
  2058.   }
  2059.  
  2060.  /***************************************************************************
  2061.   * Get the program options.                                                *
  2062.   ***************************************************************************/
  2063.  
  2064.   Profile->HideControls = FALSE ;
  2065.   Profile->fHideControls = FALSE ;
  2066.   if 
  2067.   ( 
  2068.     PrfQueryProfileSize ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("HideControls"), &Size )
  2069.     AND
  2070.     ( ( Size == sizeof(Profile->HideControls) ) OR ( Size == sizeof(short) ) )
  2071.     AND
  2072.     PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("HideControls"), &Profile->HideControls, &Size )
  2073.   )
  2074.   {
  2075.     Profile->fHideControls = TRUE ;
  2076.   }
  2077.  
  2078.   Profile->Float = FALSE ;
  2079.   Profile->fFloat = FALSE ;
  2080.   if 
  2081.   ( 
  2082.     PrfQueryProfileSize ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("Float"), &Size )
  2083.     AND
  2084.     ( ( Size == sizeof(Profile->Float) ) OR ( Size == sizeof(short) ) )
  2085.     AND
  2086.     PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("Float"), &Profile->Float, &Size )
  2087.   )
  2088.   {
  2089.     Profile->fFloat = TRUE ;
  2090.   }
  2091.  
  2092.   Profile->Animate = FALSE ;
  2093.   Profile->fAnimate = FALSE ;
  2094.   if
  2095.   (
  2096.     PrfQueryProfileSize ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("Animate"), &Size )
  2097.     AND
  2098.     ( ( Size == sizeof(Profile->Animate) ) OR ( Size == sizeof(short) ) )
  2099.     AND
  2100.     PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("Animate"), &Profile->Animate, &Size )
  2101.   )
  2102.   {
  2103.     Profile->fAnimate = TRUE ;
  2104.   }
  2105.  
  2106.   Profile->TimerInterval = 1000 ;
  2107.   Profile->fTimerInterval = FALSE ;
  2108.   if 
  2109.   ( 
  2110.     PrfQueryProfileSize ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("TimerInterval"), &Size )
  2111.     AND
  2112.     ( ( Size == sizeof(Profile->TimerInterval) ) OR ( Size == sizeof(short) ) )
  2113.     AND
  2114.     PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("TimerInterval"), &Profile->TimerInterval, &Size ) 
  2115.   )
  2116.   {
  2117.     Profile->fTimerInterval = TRUE ;
  2118.   }
  2119.  
  2120.  /***************************************************************************
  2121.   * Get the presentation parameters.                                        *
  2122.   ***************************************************************************/
  2123.  
  2124.   strcpy ( PCHAR(Profile->FontNameSize), "" ) ;
  2125.   Profile->fFontNameSize = FALSE ;
  2126.   if
  2127.   (
  2128.     PrfQueryProfileSize ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("FontNameSize"), &Size )
  2129.     AND
  2130.     ( Size == sizeof(Profile->FontNameSize) )
  2131.     AND
  2132.     PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("FontNameSize"), &Profile->FontNameSize, &Size )
  2133.   )
  2134.   {
  2135.     Profile->fFontNameSize = TRUE ;
  2136.   }
  2137.  
  2138.   Profile->BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  2139.   Profile->fBackColor = FALSE ;
  2140.   if
  2141.   (
  2142.     PrfQueryProfileSize ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("BackgroundColor"), &Size )
  2143.     AND
  2144.     ( Size == sizeof(Profile->BackColor) )
  2145.     AND
  2146.     PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("BackgroundColor"), &Profile->BackColor, &Size )
  2147.   )
  2148.   {
  2149.     Profile->fBackColor = TRUE ;
  2150.   }
  2151.  
  2152.   Profile->TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  2153.   Profile->fTextColor = FALSE ;
  2154.   if
  2155.   (
  2156.     PrfQueryProfileSize ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("ForegroundColor"), &Size )
  2157.     AND
  2158.     ( Size == sizeof(Profile->TextColor) )
  2159.     AND
  2160.     PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), PSZ("ForegroundColor"), &Profile->TextColor, &Size )
  2161.   )
  2162.   {
  2163.     Profile->fTextColor = TRUE ;
  2164.   }
  2165.  
  2166.  /***************************************************************************
  2167.   * Initialize the global resource strings.                                 *
  2168.   ***************************************************************************/
  2169.  
  2170.   Profile->Day        = new ResourceString ( Library, IDS_DAY ) ;
  2171.   Profile->Days       = new ResourceString ( Library, IDS_DAYS ) ;
  2172.   Profile->DaysOfWeek = new ResourceString ( Library, IDS_DAYSOFWEEK ) ;
  2173.   Profile->DriveError = new ResourceString ( Library, IDS_DRIVEERROR ) ;
  2174.  
  2175.  /***************************************************************************
  2176.   * Get country information.                                                *
  2177.   ***************************************************************************/
  2178.  
  2179.   COUNTRYCODE CountryCode ;
  2180.   ULONG Count ;
  2181.   ULONG Status ;
  2182.  
  2183.   CountryCode.country = 0 ;
  2184.   CountryCode.codepage = 0 ;
  2185.  
  2186.   Status = DosGetCtryInfo ( sizeof(Profile->CountryInfo), &CountryCode,
  2187.     &Profile->CountryInfo, &Count ) ;
  2188.   if ( Status )
  2189.   {
  2190.     Profile->CountryInfo.fsDateFmt = DATEFMT_MM_DD_YY ;
  2191.     Profile->CountryInfo.fsTimeFmt = 0 ;
  2192.     Profile->CountryInfo.szDateSeparator[0] = '/' ;
  2193.     Profile->CountryInfo.szDateSeparator[1] = 0 ;
  2194.     Profile->CountryInfo.szTimeSeparator[0] = ':' ;
  2195.     Profile->CountryInfo.szTimeSeparator[1] = 0 ;
  2196.     Profile->CountryInfo.szThousandsSeparator[0] = ',' ;
  2197.     Profile->CountryInfo.szThousandsSeparator[1] = 0 ;
  2198.   }
  2199.  
  2200.  /***************************************************************************
  2201.   * Get the SWAPPATH statement from CONFIG.SYS.                             *
  2202.   ***************************************************************************/
  2203.  
  2204.   PSZ Swappath = ScanSystemConfig ( Anchor, PSZ("SWAPPATH") ) ;
  2205.  
  2206.   if ( Swappath == NULL )
  2207.   {
  2208.     Swappath = PSZ("C:\\OS2\\SYSTEM 0") ;
  2209.   }
  2210.  
  2211.   sscanf ( PCHAR(Swappath), "%s %li",
  2212.     Profile->SwapPath, &Profile->MinFree ) ;
  2213.  
  2214.  /***************************************************************************
  2215.   * Find out where the spool work directory is.                             *
  2216.   ***************************************************************************/
  2217.  
  2218.   Profile->SpoolPath = PSZ(NULL) ;
  2219.  
  2220.   if ( PrfQueryProfileSize ( HINI_PROFILE, PSZ("PM_SPOOLER"), PSZ("DIR"), &Size ) )
  2221.   {
  2222.     Profile->SpoolPath = PSZ ( malloc ( (int)Size ) ) ;
  2223.  
  2224.     if ( Profile->SpoolPath )
  2225.     {
  2226.       if ( PrfQueryProfileData ( HINI_PROFILE, PSZ("PM_SPOOLER"), PSZ("DIR"), Profile->SpoolPath, &Size ) )
  2227.       {
  2228.         PBYTE p = PBYTE( strchr ( PCHAR(Profile->SpoolPath), ';' ) ) ;
  2229.         if ( p )
  2230.         {
  2231.           *p = 0 ;
  2232.         }
  2233.       }
  2234.       else
  2235.       {
  2236.         free ( Profile->SpoolPath ) ;
  2237.         Profile->SpoolPath = PSZ(NULL) ;
  2238.       }
  2239.     }
  2240.   }
  2241.  
  2242.   if ( Profile->SpoolPath == PSZ(NULL) )
  2243.      Profile->SpoolPath = PSZ ( "C:\\SPOOL" ) ;
  2244.  
  2245.  /***************************************************************************
  2246.   * Calibrate the old-style load meter, if the high resolution timer's      *
  2247.   *   available.                                                            *
  2248.   ***************************************************************************/
  2249.  
  2250.   Profile->MaxCount = CalibrateLoadMeter ( ) ;
  2251.   Profile->MaxCount = (ULONG) max ( 1L, Profile->MaxCount ) ;
  2252.  
  2253.  /***************************************************************************
  2254.   * Build the fixed portion of the item list.                               *
  2255.   ***************************************************************************/
  2256.  
  2257.   ResourceString ClockLabel ( Library, IDS_SHOW_CLOCK_LABEL ) ;
  2258.   ResourceString ClockOption ( Library, IDS_SHOW_CLOCK_OPTION ) ;
  2259.   Profile->Items[ITEM_CLOCK] = new Clock ( ITEM_CLOCK,
  2260.     PSZ("ShowClock"), PSZ(ClockLabel), PSZ(ClockOption),
  2261.     Profile->CountryInfo, Profile->DaysOfWeek ) ;
  2262.  
  2263.   ResourceString ElapsedLabel ( Library, IDS_SHOW_ELAPSED_LABEL ) ;
  2264.   ResourceString ElapsedOption ( Library, IDS_SHOW_ELAPSED_OPTION ) ;
  2265.   Profile->Items[ITEM_ELAPSEDTIME] = new ElapsedTime ( ITEM_ELAPSEDTIME,
  2266.     PSZ("ShowElapsed"), PSZ(ElapsedLabel), PSZ(ElapsedOption),
  2267.     Profile->CountryInfo,
  2268.     Profile->Day,
  2269.     Profile->Days ) ;
  2270.  
  2271.   ResourceString SwapSizeLabel ( Library, IDS_SHOW_SWAPSIZE_LABEL ) ;
  2272.   ResourceString SwapSizeOption ( Library, IDS_SHOW_SWAPSIZE_OPTION ) ;
  2273.   Profile->Items[ITEM_SWAPFILESIZE] = new SwapSize ( ITEM_SWAPFILESIZE,
  2274.     PSZ("ShowSwapsize"), PSZ(SwapSizeLabel), PSZ(SwapSizeOption),
  2275.     Profile->CountryInfo,
  2276.     Profile->SwapPath ) ;
  2277.  
  2278.   ResourceString SwapFreeLabel ( Library, IDS_SHOW_SWAPFREE_LABEL ) ;
  2279.   ResourceString SwapFreeOption ( Library, IDS_SHOW_SWAPFREE_OPTION ) ;
  2280.   Profile->Items[ITEM_SWAPDISKFREE] = new SwapFree ( ITEM_SWAPDISKFREE,
  2281.     PSZ("ShowSwapfree"), PSZ(SwapFreeLabel), PSZ(SwapFreeOption),
  2282.     Profile->CountryInfo,
  2283.     Profile->SwapPath,
  2284.     Profile->MinFree ) ;
  2285.  
  2286.   ResourceString MemoryLabel ( Library, IDS_SHOW_MEMORY_LABEL ) ;
  2287.   ResourceString MemoryOption ( Library, IDS_SHOW_MEMORY_OPTION ) ;
  2288.   Profile->Items[ITEM_MEMORYFREE] = new MemoryFree ( ITEM_MEMORYFREE,
  2289.     PSZ("ShowMemory"), PSZ(MemoryLabel), PSZ(MemoryOption),
  2290.     Profile->CountryInfo,
  2291.     (SwapFree*)Profile->Items[ITEM_SWAPDISKFREE] ) ;
  2292.  
  2293.   ResourceString SpoolSizeLabel ( Library, IDS_SHOW_SPOOLSIZE_LABEL ) ;
  2294.   ResourceString SpoolSizeOption ( Library, IDS_SHOW_SPOOLSIZE_OPTION ) ;
  2295.   Profile->Items[ITEM_SPOOLFILESIZE] = new SpoolSize ( ITEM_SPOOLFILESIZE,
  2296.     PSZ("ShowSpoolSize"), PSZ(SpoolSizeLabel), PSZ(SpoolSizeOption),
  2297.     Profile->CountryInfo,
  2298.     Profile->SpoolPath ) ;
  2299.  
  2300.   ResourceString CpuLoadLabel ( Library, IDS_SHOW_CPULOAD_LABEL ) ;
  2301.   ResourceString CpuLoadOption ( Library, IDS_SHOW_CPULOAD_OPTION ) ;
  2302.   Profile->Items[ITEM_CPULOAD] = new CpuLoad ( ITEM_CPULOAD,
  2303.     PSZ("ShowCpuLoad"), PSZ(CpuLoadLabel), PSZ(CpuLoadOption),
  2304.     Profile->MaxCount,
  2305.     &Profile->IdleCount ) ;
  2306.  
  2307.   ResourceString TaskCountLabel ( Library, IDS_SHOW_TASKCOUNT_LABEL ) ;
  2308.   ResourceString TaskCountOption ( Library, IDS_SHOW_TASKCOUNT_OPTION ) ;
  2309.   Profile->Items[ITEM_TASKCOUNT] = new TaskCount ( ITEM_TASKCOUNT,
  2310.     PSZ("ShowTaskCount"), PSZ(TaskCountLabel), PSZ(TaskCountOption),
  2311.     Anchor ) ;
  2312.  
  2313.   ResourceString TotalFreeLabel ( Library, IDS_SHOW_TOTALFREE_LABEL ) ;
  2314.   ResourceString TotalFreeOption ( Library, IDS_SHOW_TOTALFREE_OPTION ) ;
  2315.   Profile->Items[ITEM_TOTALFREE] = new TotalFree ( ITEM_TOTALFREE,
  2316.     PSZ("ShowTotalFree"), PSZ(TotalFreeLabel), PSZ(TotalFreeOption),
  2317.     Profile->CountryInfo, 0 ) ;
  2318.  
  2319.   for ( int i=0; i<ITEM_BASE_COUNT; i++ )
  2320.   {
  2321.     BOOL Flag = TRUE ;
  2322.     if 
  2323.     ( 
  2324.       PrfQueryProfileSize ( ProfileHandle, PSZ(PROGRAM_NAME), Profile->Items[i]->QueryName(), &Size )
  2325.       AND
  2326.       ( ( Size == sizeof(Flag) ) OR ( Size == sizeof(short) ) )
  2327.       AND 
  2328.       PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), Profile->Items[i]->QueryName(), &Flag, &Size )
  2329.     )
  2330.     {
  2331.       ;
  2332.     }
  2333.  
  2334.     if ( Flag )
  2335.       Profile->Items[i]->SetFlag() ;
  2336.     else
  2337.       Profile->Items[i]->ResetFlag() ;
  2338.   }
  2339.  
  2340.  /***************************************************************************
  2341.   * Add items for each drive on the system.                                 *
  2342.   ***************************************************************************/
  2343.  
  2344.   ULONG Drive, Drives ;
  2345.   DosQueryCurrentDisk ( &Drive, &Drives ) ;
  2346.   UpdateDriveList ( Anchor, Library, ProfileHandle, Profile, 0, Drives ) ;
  2347.  
  2348.   return ( 0 ) ;
  2349. }
  2350.  
  2351. /****************************************************************************
  2352.  *                                                                          *
  2353.  *                           Put Profile Data                               *
  2354.  *                                                                          *
  2355.  ****************************************************************************/
  2356.  
  2357. STATIC void PutProfile ( HINI ProfileHandle, PPROFILE Profile )
  2358. {
  2359.  /***************************************************************************
  2360.   * Save the window's current size and position.                            *
  2361.   ***************************************************************************/
  2362.  
  2363.   PrfWriteProfileData
  2364.   (
  2365.     ProfileHandle,
  2366.     PSZ(PROGRAM_NAME),
  2367.     PSZ("Position"),
  2368.     &Profile->Position,
  2369.     sizeof(Profile->Position)
  2370.   ) ;
  2371.  
  2372.  /***************************************************************************
  2373.   * Save the program options.                                               *
  2374.   ***************************************************************************/
  2375.  
  2376.   if ( Profile->fHideControls )
  2377.   {
  2378.     PrfWriteProfileData
  2379.     (
  2380.       ProfileHandle,
  2381.       PSZ(PROGRAM_NAME),
  2382.       PSZ("HideControls"),
  2383.       &Profile->HideControls,
  2384.       sizeof(Profile->HideControls)
  2385.     ) ;
  2386.   }
  2387.  
  2388.   if ( Profile->fFloat )
  2389.   {
  2390.     PrfWriteProfileData
  2391.     (
  2392.       ProfileHandle,
  2393.       PSZ(PROGRAM_NAME),
  2394.       PSZ("Float"),
  2395.       &Profile->Float,
  2396.       sizeof(Profile->Float)
  2397.     ) ;
  2398.   }
  2399.  
  2400.   if ( Profile->fAnimate )
  2401.   {
  2402.     PrfWriteProfileData
  2403.     (
  2404.       ProfileHandle,
  2405.       PSZ(PROGRAM_NAME),
  2406.       PSZ("Animate"),
  2407.       &Profile->Animate,
  2408.       sizeof(Profile->Animate)
  2409.     ) ;
  2410.   }
  2411.  
  2412.   if ( Profile->fTimerInterval )
  2413.   {
  2414.     PrfWriteProfileData
  2415.     (
  2416.       ProfileHandle,
  2417.       PSZ(PROGRAM_NAME),
  2418.       PSZ("TimerInterval"),
  2419.       &Profile->TimerInterval,
  2420.       sizeof(Profile->TimerInterval)
  2421.     ) ;
  2422.   }
  2423.  
  2424.  /***************************************************************************
  2425.   * Save the item options.                                                  *
  2426.   ***************************************************************************/
  2427.  
  2428.   for ( int i=0; i<Profile->ItemCount; i++ )
  2429.   {
  2430.     Item *pItem = Profile->Items [i] ;
  2431.     BOOL Flag = pItem->QueryFlag() ;
  2432.  
  2433.     PrfWriteProfileData
  2434.     (
  2435.       ProfileHandle,
  2436.       PSZ(PROGRAM_NAME),
  2437.       pItem->QueryName(),
  2438.       &Flag,
  2439.       sizeof(Flag)
  2440.     ) ;
  2441.   }
  2442.  
  2443.  /***************************************************************************
  2444.   * Save the presentation parameters.                                       *
  2445.   ***************************************************************************/
  2446.  
  2447.   if ( Profile->fFontNameSize )
  2448.   {
  2449.     PrfWriteProfileData
  2450.     (
  2451.       ProfileHandle,
  2452.       PSZ(PROGRAM_NAME),
  2453.       PSZ("FontNameSize"),
  2454.       Profile->FontNameSize,
  2455.       sizeof(Profile->FontNameSize)
  2456.     ) ;
  2457.   }
  2458.  
  2459.   if ( Profile->fBackColor )
  2460.   {
  2461.     PrfWriteProfileData
  2462.     (
  2463.       ProfileHandle,
  2464.       PSZ(PROGRAM_NAME),
  2465.       PSZ("BackgroundColor"),
  2466.       &Profile->BackColor,
  2467.       sizeof(Profile->BackColor)
  2468.     ) ;
  2469.   }
  2470.  
  2471.   if ( Profile->fTextColor )
  2472.   {
  2473.     PrfWriteProfileData
  2474.     (
  2475.       ProfileHandle,
  2476.       PSZ(PROGRAM_NAME),
  2477.       PSZ("ForegroundColor"),
  2478.       &Profile->TextColor,
  2479.       sizeof(Profile->TextColor)
  2480.     ) ;
  2481.   }
  2482. }
  2483.  
  2484. /****************************************************************************
  2485.  *                                                                          *
  2486.  *      Scan CONFIG.SYS for a keyword.  Return the value.                   *
  2487.  *                                                                          *
  2488.  ****************************************************************************/
  2489.  
  2490. STATIC PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword )
  2491. {
  2492.  /***************************************************************************
  2493.   * Get the boot drive number from the global information segment.          *
  2494.   ***************************************************************************/
  2495.  
  2496.   ULONG BootDrive ;
  2497.   DosQuerySysInfo ( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &BootDrive, sizeof(BootDrive) ) ;
  2498.  
  2499.  /***************************************************************************
  2500.   * Convert the keyword to upper case.                                      *
  2501.   ***************************************************************************/
  2502.  
  2503.   WinUpper ( Anchor, 0, 0, Keyword ) ;
  2504.  
  2505.  /***************************************************************************
  2506.   * Build the CONFIG.SYS path.                                              *
  2507.   ***************************************************************************/
  2508.  
  2509.   char Path [_MAX_PATH] ;
  2510.   Path[0] = (char) ( BootDrive + 'A' - 1 ) ;
  2511.   Path[1] = 0 ;
  2512.   strcat ( Path, ":\\CONFIG.SYS" ) ;
  2513.  
  2514.  /***************************************************************************
  2515.   * Open CONFIG.SYS for reading.                                            *
  2516.   ***************************************************************************/
  2517.  
  2518.   FILE *File = fopen ( Path, "r" ) ;
  2519.   if ( NOT File )
  2520.   {
  2521.     return ( PSZ(NULL) ) ;
  2522.   }
  2523.  
  2524.  /***************************************************************************
  2525.   * While there're more lines in CONFIG.SYS, read a line and check it.      *
  2526.   ***************************************************************************/
  2527.  
  2528.   static char Buffer [500] ;
  2529.   while ( fgets ( Buffer, sizeof(Buffer), File ) )
  2530.   {
  2531.  
  2532.    /*************************************************************************
  2533.     * Clean any trailing newline character from the input string.           *
  2534.     *************************************************************************/
  2535.  
  2536.     if ( Buffer[strlen(Buffer)-1] == '\n' )
  2537.     {
  2538.       Buffer[strlen(Buffer)-1] = 0 ;
  2539.     }
  2540.  
  2541.    /*************************************************************************
  2542.     * If keyword starts the line, we've found the line we want.  Close      *
  2543.     *   the file and return a pointer to the parameter text.                *
  2544.     *************************************************************************/
  2545.  
  2546.     WinUpper ( Anchor, 0, 0, PSZ(Buffer) ) ;
  2547.  
  2548.     if ( NOT strncmp ( Buffer, PCHAR(Keyword), strlen(PCHAR(Keyword)) )
  2549.       AND ( Buffer[strlen(PCHAR(Keyword))] == '=' ) )
  2550.     {
  2551.       fclose ( File ) ;
  2552.       return ( PSZ( Buffer + strlen(PCHAR(Keyword)) + 1 ) ) ;
  2553.     }
  2554.   }
  2555.  
  2556.  /***************************************************************************
  2557.   * Close the file.  We haven't found the line we wanted.                   *
  2558.   ***************************************************************************/
  2559.  
  2560.   fclose ( File ) ;
  2561.  
  2562.   return ( PSZ(NULL) ) ;
  2563. }
  2564.  
  2565. /****************************************************************************
  2566.  *                                                                          *
  2567.  *                       Resize Client Window                               *
  2568.  *                                                                          *
  2569.  ****************************************************************************/
  2570.  
  2571. STATIC void ResizeWindow ( HWND hwnd, PPROFILE Profile )
  2572. {
  2573.  /***************************************************************************
  2574.   * If the window is visible and minimized, restore it invisibly.           *
  2575.   ***************************************************************************/
  2576.  
  2577.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  2578.  
  2579.   SHORT fHadToHide = FALSE ;
  2580.   SHORT fHadToRestore = FALSE ;
  2581.   if ( Profile->Position.fl & SWP_MINIMIZE )
  2582.   {
  2583.     if ( WinIsWindowVisible ( hwndFrame ) )
  2584.     {
  2585.       WinShowWindow ( hwndFrame, FALSE ) ;
  2586.       fHadToHide = TRUE ;
  2587.     }
  2588.     WinSetWindowPos ( hwndFrame, 0, 0, 0, 0, 0, SWP_RESTORE ) ;
  2589.     fHadToRestore = TRUE ;
  2590.   }
  2591.  
  2592.  /***************************************************************************
  2593.   * Determine how many items are to be displayed.                           *
  2594.   ***************************************************************************/
  2595.  
  2596.   HPS hPS = WinGetPS ( hwnd ) ;
  2597.  
  2598.   int Count = 0 ;
  2599.   LONG Widest = 0 ;
  2600.   LONG Height = 0 ;
  2601.  
  2602.   for ( int i=0; i<Profile->ItemCount; i++ )
  2603.   {
  2604.     Item *pItem = Profile->Items [i] ;
  2605.  
  2606.     if ( pItem->QueryFlag() )
  2607.     {
  2608.       Count ++ ;
  2609.  
  2610.       BYTE Text [100] ;
  2611.       sprintf ( PCHAR(Text), "%s 1,234,567K", pItem->QueryLabel() ) ;
  2612.  
  2613.       RECTL Rectangle ;
  2614.       WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  2615.  
  2616.       WinDrawText ( hPS, strlen(PCHAR(Text)), Text,
  2617.         &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  2618.  
  2619.       Widest = max ( Widest, (Rectangle.xRight-Rectangle.xLeft+1) ) ;
  2620.  
  2621.       Height += Rectangle.yTop - Rectangle.yBottom ;
  2622.     }
  2623.   }
  2624.  
  2625.   WinReleasePS ( hPS ) ;
  2626.  
  2627.  /***************************************************************************
  2628.   * Get the window's current size & position.                               *
  2629.   ***************************************************************************/
  2630.  
  2631.   RECTL Rectangle ;
  2632.   WinQueryWindowRect ( hwndFrame, &Rectangle ) ;
  2633.  
  2634.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  2635.  
  2636.  /***************************************************************************
  2637.   * Adjust the window's width & height.                                     *
  2638.   ***************************************************************************/
  2639.  
  2640.   Rectangle.xRight  = Rectangle.xLeft + Widest ;
  2641.  
  2642.   Rectangle.yTop    = Rectangle.yBottom + Height ;
  2643.  
  2644.  /***************************************************************************
  2645.   * Compute new frame size and apply it.                                    *
  2646.   ***************************************************************************/
  2647.  
  2648.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  2649.  
  2650.   WinSetWindowPos ( hwndFrame, 0, 0, 0,
  2651.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2652.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2653.     SWP_SIZE ) ;
  2654.  
  2655.  /***************************************************************************
  2656.   * Return the window to its original state.                                *
  2657.   ***************************************************************************/
  2658.  
  2659.   if ( fHadToRestore )
  2660.   {
  2661.     WinSetWindowPos ( hwndFrame, 0,
  2662.       Profile->Position.x, Profile->Position.y,
  2663.       Profile->Position.cx, Profile->Position.cy,
  2664.       SWP_MOVE | SWP_SIZE | SWP_MINIMIZE ) ;
  2665.   }
  2666.  
  2667.   if ( fHadToHide )
  2668.   {
  2669.     WinShowWindow ( hwndFrame, TRUE ) ;
  2670.   }
  2671.  
  2672.  /***************************************************************************
  2673.   * Invalidate the window so that it gets repainted.                        *
  2674.   ***************************************************************************/
  2675.  
  2676.   WinInvalidateRect ( hwnd, PRECTL(NULL), TRUE ) ;
  2677. }
  2678.  
  2679. /****************************************************************************
  2680.  *                                                                          *
  2681.  *                      Hide Window Controls                                *
  2682.  *                                                                          *
  2683.  ****************************************************************************/
  2684.  
  2685. STATIC void HideControls
  2686. (
  2687.   BOOL fHide,
  2688.   HWND hwndFrame,
  2689.   HWND hwndSysMenu,
  2690.   HWND hwndTitleBar,
  2691.   HWND hwndMinMax
  2692. )
  2693. {
  2694.  /***************************************************************************
  2695.   * Get original window position and state.                                 *
  2696.   ***************************************************************************/
  2697.  
  2698.   SWP OldPosition ;
  2699.   WinQueryWindowPos ( hwndFrame, &OldPosition ) ;
  2700.  
  2701.   BOOL WasVisible = WinIsWindowVisible ( hwndFrame ) ;
  2702.  
  2703.  /***************************************************************************
  2704.   * Restore and hide the window.                                            *
  2705.   ***************************************************************************/
  2706.  
  2707.   WinSetWindowPos ( hwndFrame, 0, 0, 0, 0, 0, SWP_RESTORE | SWP_HIDE ) ;
  2708.  
  2709.  /***************************************************************************
  2710.   * Determine client window and location.                                   *
  2711.   ***************************************************************************/
  2712.  
  2713.   SWP Position ;
  2714.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  2715.  
  2716.   RECTL Rectangle ;
  2717.   Rectangle.xLeft   = Position.x ;
  2718.   Rectangle.xRight  = Position.x + Position.cx ;
  2719.   Rectangle.yBottom = Position.y ;
  2720.   Rectangle.yTop    = Position.y + Position.cy ;
  2721.  
  2722.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  2723.  
  2724.  /***************************************************************************
  2725.   * Hide or reveal the controls windows by changing their parentage.        *
  2726.   ***************************************************************************/
  2727.  
  2728.   if ( fHide )
  2729.   {
  2730.     WinSetParent ( hwndSysMenu,  HWND_OBJECT, FALSE ) ;
  2731.     WinSetParent ( hwndTitleBar, HWND_OBJECT, FALSE ) ;
  2732.     WinSetParent ( hwndMinMax,   HWND_OBJECT, FALSE ) ;
  2733.   }
  2734.   else
  2735.   {
  2736.     WinSetParent ( hwndSysMenu,  hwndFrame, TRUE ) ;
  2737.     WinSetParent ( hwndTitleBar, hwndFrame, TRUE ) ;
  2738.     WinSetParent ( hwndMinMax,   hwndFrame, TRUE ) ;
  2739.   }
  2740.  
  2741.  /***************************************************************************
  2742.   * Tell the frame that things have changed.  Let it update the window.     *
  2743.   ***************************************************************************/
  2744.  
  2745.   WinSendMsg ( hwndFrame, WM_UPDATEFRAME,
  2746.     MPFROMSHORT ( FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON ), 0L ) ;
  2747.  
  2748.  /***************************************************************************
  2749.   * Reposition the frame around the client window, which is left be.        *
  2750.   ***************************************************************************/
  2751.  
  2752.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  2753.  
  2754.   WinSetWindowPos ( hwndFrame, 0,
  2755.     (SHORT) Rectangle.xLeft,  (SHORT) Rectangle.yBottom,
  2756.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2757.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2758.     SWP_SIZE | SWP_MOVE ) ;
  2759.  
  2760.  /***************************************************************************
  2761.   * If window was maximized, put it back that way.                          *
  2762.   ***************************************************************************/
  2763.  
  2764.   if ( OldPosition.fl & SWP_MAXIMIZE )
  2765.   {
  2766.     WinSetWindowPos ( hwndFrame, 0,
  2767.       (SHORT) Rectangle.xLeft,  (SHORT) Rectangle.yBottom,
  2768.       (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2769.       (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2770.       SWP_SIZE | SWP_MOVE |
  2771.       ( OldPosition.fl & SWP_MAXIMIZE ) ) ;
  2772.   }
  2773.  
  2774.  /***************************************************************************
  2775.   * If the window was visible in the first place, show it.                  *
  2776.   ***************************************************************************/
  2777.  
  2778.   if ( WasVisible )
  2779.   {
  2780.     WinShowWindow ( hwndFrame, TRUE ) ;
  2781.   }
  2782. }
  2783.  
  2784. /****************************************************************************
  2785.  *                                                                          *
  2786.  *    Update Window                                                         *
  2787.  *                                                                          *
  2788.  ****************************************************************************/
  2789.  
  2790. STATIC void UpdateWindow ( HWND hwnd, PDATA Data, BOOL All )
  2791. {
  2792.  /***************************************************************************
  2793.   * Determine how many items are to be displayed.                           *
  2794.   ***************************************************************************/
  2795.  
  2796.   int Count = 0 ;
  2797.   for ( int i=0; i<Data->Profile.ItemCount; i++ )
  2798.   {
  2799.     if ( Data->Profile.Items[i]->QueryFlag() )
  2800.     {
  2801.       Count ++ ;
  2802.     }
  2803.   }
  2804.  
  2805.  /***************************************************************************
  2806.   * Get presentation space and make it use RGB colors.                      *
  2807.   ***************************************************************************/
  2808.  
  2809.   HPS hPS = WinGetPS ( hwnd ) ;
  2810.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, PLONG(NULL) ) ;
  2811.  
  2812.  /***************************************************************************
  2813.   * Get the window's size and determine the initial position.               *
  2814.   ***************************************************************************/
  2815.  
  2816.   RECTL Rectangle ;
  2817.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  2818.  
  2819.   Rectangle.xLeft += Data->Width / 2 ;
  2820.   Rectangle.xRight -= Data->Width / 2 ;
  2821.  
  2822.   Rectangle.yBottom = Data->Height * ( Count - 1 ) ;
  2823.   Rectangle.yTop = Rectangle.yBottom + Data->Height ;
  2824.  
  2825.  /***************************************************************************
  2826.   * Review all items.  Display those changed, or all.                       *
  2827.   ***************************************************************************/
  2828.  
  2829.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  2830.   {
  2831.     ULONG NewValue ;
  2832.  
  2833.     Item *pItem = Data->Profile.Items [i] ;
  2834.  
  2835.     if ( pItem->QueryFlag() )
  2836.     {
  2837.       pItem->Repaint ( hPS, Rectangle,
  2838.         Data->Profile.TextColor, Data->Profile.BackColor, All ) ;
  2839.  
  2840.       Rectangle.yBottom -= Data->Height ;
  2841.       Rectangle.yTop    -= Data->Height ;
  2842.     }
  2843.   }
  2844.  
  2845.  /***************************************************************************
  2846.   * Release the presentation space and return.                              *
  2847.   ***************************************************************************/
  2848.  
  2849.   WinReleasePS ( hPS ) ;
  2850. }
  2851.  
  2852.  
  2853. /****************************************************************************
  2854.  *                                                                          *
  2855.  *    Monitor Loop Thread                                                   *
  2856.  *                                                                          *
  2857.  ****************************************************************************/
  2858.  
  2859. STATIC VOID _Optlink MonitorLoopThread ( PVOID Parameter )
  2860. {
  2861.  /***************************************************************************
  2862.   * Get the thread parameter.                                               *
  2863.   ***************************************************************************/
  2864.  
  2865.   PMONITOR_PARMS Parms = PMONITOR_PARMS ( Parameter ) ;
  2866.  
  2867.  /***************************************************************************
  2868.   * Set this thread's priority as high as it can go.                        *
  2869.   ***************************************************************************/
  2870.  
  2871.   DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0 ) ;
  2872.  
  2873.  /***************************************************************************
  2874.   * Start up the high resolution timer, if it is available.                 *
  2875.   ***************************************************************************/
  2876.  
  2877.   BOOL HiResTimer = OpenTimer ( ) ;
  2878.  
  2879.  /***************************************************************************
  2880.   * Loop forever . . .                                                      *
  2881.   ***************************************************************************/
  2882.  
  2883.   while ( Parms->Active )
  2884.   {
  2885.  
  2886.    /*************************************************************************
  2887.     * Reset the last time and count seen.                                   *
  2888.     *************************************************************************/
  2889.  
  2890.     ULONG LastMilliseconds ;
  2891.     TIMESTAMP Time [2] ;
  2892.  
  2893.     if ( HiResTimer )
  2894.       GetTime ( &Time[0] ) ;
  2895.     else
  2896.       DosQuerySysInfo ( QSV_MS_COUNT, QSV_MS_COUNT, &LastMilliseconds, sizeof(LastMilliseconds) ) ;
  2897.  
  2898.     ULONG LastCounter = *Parms->Counter ;
  2899.  
  2900.    /*************************************************************************
  2901.     * Sleep for a bit.                                                      *
  2902.     *************************************************************************/
  2903.  
  2904.     DosSleep ( *Parms->Interval ) ;
  2905.  
  2906.    /*************************************************************************
  2907.     * Find out how much time and counts went by.                            *
  2908.     *************************************************************************/
  2909.  
  2910.     ULONG CurrentCounter = *Parms->Counter ;
  2911.  
  2912.     ULONG DeltaMilliseconds ;
  2913.  
  2914.     if ( HiResTimer )
  2915.     {
  2916.       GetTime ( &Time[1] ) ;
  2917.  
  2918.       ULONG Nanoseconds ;
  2919.       DeltaMilliseconds = ComputeElapsedTime ( &Time[0], &Time[1], &Nanoseconds ) ;
  2920.  
  2921.       if ( Nanoseconds >= 500000L )
  2922.         DeltaMilliseconds ++ ;
  2923.     }
  2924.     else
  2925.     {
  2926.       ULONG Milliseconds ;
  2927.       DosQuerySysInfo ( QSV_MS_COUNT, QSV_MS_COUNT, &Milliseconds, sizeof(Milliseconds) ) ;
  2928.       DeltaMilliseconds = Milliseconds - LastMilliseconds ;
  2929.     }
  2930.  
  2931.    /*************************************************************************
  2932.     * Find out how much idle time was counted.  Adjust it to persecond.     *
  2933.     *************************************************************************/
  2934.  
  2935.     ULONG Counter = (ULONG) ( ( (double)(CurrentCounter-LastCounter) * 1000L ) / (double)DeltaMilliseconds ) ;
  2936.  
  2937.    /*************************************************************************
  2938.     * Tell the owner window to refresh its statistics.                      *
  2939.     *************************************************************************/
  2940.  
  2941.     WinPostMsg ( Parms->Owner, WM_REFRESH, MPFROMLONG(Counter), 0L ) ;
  2942.   }
  2943. }
  2944.  
  2945. /****************************************************************************
  2946.  *                                                                          *
  2947.  *      Update the Item List to reflect changes in the available drives.    *
  2948.  *                                                                          *
  2949.  ****************************************************************************/
  2950.  
  2951. STATIC VOID UpdateDriveList
  2952. (
  2953.   HAB Anchor,
  2954.   HMODULE Library,
  2955.   HINI ProfileHandle,
  2956.   PPROFILE Profile,
  2957.   ULONG OldDrives,
  2958.   ULONG NewDrives
  2959. )
  2960. {
  2961.  /***************************************************************************
  2962.   * Get format strings.                                                     *
  2963.   ***************************************************************************/
  2964.  
  2965.   ResourceString LabelFormat ( Library, IDS_SHOW_DRIVE_FREE_LABEL ) ;
  2966.   ResourceString OptionFormat ( Library, IDS_SHOW_DRIVE_FREE_OPTION ) ;
  2967.  
  2968.  /***************************************************************************
  2969.   * Save the old item list for comparison.                                  *
  2970.   ***************************************************************************/
  2971.  
  2972.   Item *OldItems [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  2973.  
  2974.   memset ( OldItems, 0, sizeof(OldItems) ) ;
  2975.  
  2976.   USHORT OldCount = 0 ;
  2977.   if ( OldDrives )
  2978.   {
  2979.     OldCount = Profile->ItemCount ;
  2980.     memcpy ( OldItems, Profile->Items, sizeof(OldItems) ) ;
  2981.   }
  2982.  
  2983.  /***************************************************************************
  2984.   * Add items for each drive on the system.                                 *
  2985.   ***************************************************************************/
  2986.  
  2987.   USHORT Count = ITEM_BASE_COUNT ;
  2988.   USHORT OldIndex = ITEM_BASE_COUNT ;
  2989.  
  2990.   ULONG Drives = 0 ;
  2991.   NewDrives >>= 2 ;
  2992.   OldDrives >>= 2 ;
  2993.  
  2994.   for ( int Drive=3; Drive<=MAX_DRIVES; Drive++ )
  2995.   {
  2996.     while ( ( OldIndex < OldCount )
  2997.       AND ( (SHORT)OldItems[OldIndex]->QueryId() < ITEM_BASE_COUNT + Drive ) )
  2998.     {
  2999.       OldIndex ++ ;
  3000.     }
  3001.  
  3002.     if ( NewDrives & 1 )
  3003.     {
  3004.       if ( OldDrives & 1 )
  3005.       {
  3006.         Drives |= ( 1 << (Drive-1) ) ;
  3007.         if ( ( OldIndex < OldCount )
  3008.           AND ( (SHORT)OldItems[OldIndex]->QueryId() == ITEM_BASE_COUNT + Drive ) )
  3009.         {
  3010.           Profile->Items[Count++] = OldItems[OldIndex++] ;
  3011.         }
  3012.       }
  3013.       else
  3014.       {
  3015.         BYTE FileSystem [80] ;
  3016.         if ( CheckDrive ( Drive, FileSystem ) )
  3017.         {
  3018.           Drives |= ( 1 << (Drive-1) ) ;
  3019.  
  3020.           BYTE Name [80] ;
  3021.           sprintf ( PCHAR(Name),   "ShowDrive%c:", Drive+'A'-1 ) ;
  3022.  
  3023.           BYTE Label [80] ;
  3024.           sprintf ( PCHAR(Label),  PCHAR(LabelFormat),  Drive+'A'-1, FileSystem ) ;
  3025.  
  3026.           BYTE Option [80] ;
  3027.           sprintf ( PCHAR(Option), PCHAR(OptionFormat), Drive+'A'-1 ) ;
  3028.  
  3029.           Profile->Items[Count++] = new DriveFree ( ITEM_BASE_COUNT+Drive,
  3030.             Name, Label, Option, Profile->CountryInfo,
  3031.             Drive, Profile->DriveError ) ;
  3032.         }
  3033.       }
  3034.     }
  3035.     else
  3036.     {
  3037.       if ( OldDrives & 1 )
  3038.       {
  3039.         delete OldItems[OldIndex++] ;
  3040.       }
  3041.       else
  3042.       {
  3043.         // Do nothing.
  3044.       }
  3045.     }
  3046.  
  3047.     NewDrives >>= 1 ;
  3048.     OldDrives >>= 1 ;
  3049.   }
  3050.  
  3051.  /***************************************************************************
  3052.   * Save the new item count.                                                *
  3053.   ***************************************************************************/
  3054.  
  3055.   Profile->ItemCount = Count ;
  3056.  
  3057.  /***************************************************************************
  3058.   * Fetch the display flags for the drives.                                 *
  3059.   ***************************************************************************/
  3060.  
  3061.   for ( int i=ITEM_BASE_COUNT; i<Profile->ItemCount; i++ )
  3062.   {
  3063.     BOOL Flag = TRUE ;
  3064.     Item *pItem = Profile->Items [i] ;
  3065.     ULONG Size ;
  3066.  
  3067.     if
  3068.     (
  3069.       PrfQueryProfileSize ( ProfileHandle, PSZ(PROGRAM_NAME), pItem->QueryName(), &Size )
  3070.       AND
  3071.       ( ( Size == sizeof(Flag) ) OR ( Size == sizeof(short) ) )
  3072.       AND
  3073.       PrfQueryProfileData ( ProfileHandle, PSZ(PROGRAM_NAME), pItem->QueryName(), &Flag, &Size )
  3074.     )
  3075.     {
  3076.       ;
  3077.     }
  3078.  
  3079.     if ( Flag )
  3080.       pItem->SetFlag () ;
  3081.     else
  3082.       pItem->ResetFlag () ;
  3083.   }
  3084.  
  3085.  /***************************************************************************
  3086.   * Update the total free space object.                                     *
  3087.   ***************************************************************************/
  3088.  
  3089.   ( (TotalFree*) Profile->Items [ ITEM_TOTALFREE ] ) -> ResetMask ( Drives ) ;
  3090. }
  3091.  
  3092. /****************************************************************************
  3093.  *                                                                          *
  3094.  *      Check to see if drive should be added to display list.              *
  3095.  *                                                                          *
  3096.  ****************************************************************************/
  3097.  
  3098. STATIC BOOL CheckDrive ( USHORT Drive, PBYTE FileSystem )
  3099. {
  3100.  /***************************************************************************
  3101.   * First, check to see if drive is local or remote.  Remote drives are     *
  3102.   *   always monitored.                                                     *
  3103.   ***************************************************************************/
  3104.  
  3105.   BYTE Path [3] ;
  3106.   Path[0] = (BYTE) ( Drive + 'A' - 1 ) ;
  3107.   Path[1] = ':' ;
  3108.   Path[2] = 0 ;
  3109.  
  3110.   DosError ( FERR_DISABLEHARDERR ) ;
  3111.  
  3112.   BYTE Buffer [1024] ;
  3113.   ULONG Size = sizeof(Buffer) ;
  3114.   ULONG Status = DosQueryFSAttach ( Path, 0, FSAIL_QUERYNAME, (PFSQBUFFER2)Buffer, &Size ) ;
  3115.   DosError ( FERR_ENABLEHARDERR ) ;
  3116.  
  3117.   if ( Status )
  3118.   {
  3119. //  Log ( "ERROR: Unable to query drive %s for file system.  Status %04X.\r\n",
  3120. //    Path, Status ) ;
  3121.     return ( FALSE ) ;
  3122.   }
  3123.  
  3124.   USHORT cbName = PFSQBUFFER2(Buffer)->cbName ;
  3125.   strcpy ( PCHAR(FileSystem), PCHAR(PFSQBUFFER2(Buffer+cbName)->szFSDName) ) ;
  3126.  
  3127.   if ( PFSQBUFFER2(Buffer)->iType == FSAT_REMOTEDRV )
  3128.   {
  3129.     return ( TRUE ) ;
  3130.   }
  3131.  
  3132.  /***************************************************************************
  3133.   * Attempt to open the local drive as an entire device.  If unable to do   *
  3134.   *   so, we cannot monitor this drive.                                     *
  3135.   ***************************************************************************/
  3136.  
  3137.   ULONG Action ;
  3138.   HFILE Handle ;
  3139.   Status = DosOpen ( Path, &Handle, &Action, 0, 0, FILE_OPEN,
  3140.     OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
  3141.     OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR, 0 ) ;
  3142.  
  3143.   if ( Status )
  3144.   {
  3145. //  Log ( "ERROR: Unable to open local drive %s.  Status %04X.\r\n",
  3146. //    Path, Status ) ;
  3147.     return ( FALSE ) ;
  3148.   }
  3149.  
  3150.  /***************************************************************************
  3151.   * Check to see if the drive has removable media.  We cannot monitor such. *
  3152.   ***************************************************************************/
  3153.  
  3154.   BOOL Addit = FALSE ;
  3155.   BYTE Command = 0 ;
  3156.   BYTE NonRemovable ;
  3157.  
  3158.   ULONG LengthIn = sizeof(Command) ;
  3159.   ULONG LengthOut = sizeof(NonRemovable);
  3160.  
  3161.   if 
  3162.   ( 
  3163.     NOT DosDevIOCtl 
  3164.     ( 
  3165.       Handle, 8, 0x20, 
  3166.       &Command, sizeof(Command), &LengthIn,
  3167.       &NonRemovable, sizeof(NonRemovable), &LengthOut 
  3168.     ) 
  3169.   )
  3170.   {
  3171.     Addit = NonRemovable ;
  3172.   }
  3173.  
  3174.  /***************************************************************************
  3175.   * Close the drive.                                                        *
  3176.   ***************************************************************************/
  3177.  
  3178.   DosClose ( Handle ) ;
  3179.  
  3180.  /***************************************************************************
  3181.   * Return the final verdict.                                               *
  3182.   ***************************************************************************/
  3183.  
  3184.   return ( Addit ) ;
  3185. }
  3186.  
  3187. /****************************************************************************
  3188.  *                                                                          *
  3189.  *                       Calibrate the Load Meter                           *
  3190.  *                                                                          *
  3191.  ****************************************************************************/
  3192.  
  3193. STATIC ULONG CalibrateLoadMeter ( void )
  3194. {
  3195.  /***************************************************************************
  3196.   * Set result to zero as a default.                                        *
  3197.   ***************************************************************************/
  3198.  
  3199.   double AdjustedMaxLoad = 0.0 ;
  3200.  
  3201.  /***************************************************************************
  3202.   * If HRTIMER.SYS has been installed . . .                                 *
  3203.   ***************************************************************************/
  3204.  
  3205.   if ( OpenTimer ( ) )
  3206.   {
  3207.    /*************************************************************************
  3208.     * Increase this thread's priority to the maximum.                       *
  3209.     *************************************************************************/
  3210.  
  3211.     DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0 ) ;
  3212.  
  3213.    /*************************************************************************
  3214.     * Create the calibration thread and set its priority next highest.      *
  3215.     *************************************************************************/
  3216.  
  3217.     COUNTER_PARMS Parms ;
  3218.     ULONG MaxLoad ;
  3219.     Parms.Active = TRUE ;
  3220.     Parms.Counter = &MaxLoad ;
  3221.     TID tidCalibrate = _beginthread ( CounterThread, NULL, 0x3000, &Parms ) ;
  3222.     DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM-1, tidCalibrate ) ;
  3223.     DosSuspendThread ( tidCalibrate ) ;
  3224.  
  3225.    /*************************************************************************
  3226.     * Reset the calibration count, get the time, and let the counter go.    *
  3227.     *************************************************************************/
  3228.  
  3229.     MaxLoad = 0 ;
  3230.     TIMESTAMP Time[2] ;
  3231.     GetTime ( &Time[0] ) ;
  3232.     DosResumeThread ( tidCalibrate ) ;
  3233.  
  3234.    /*************************************************************************
  3235.     * Sleep for one second.                                                 *
  3236.     *************************************************************************/
  3237.  
  3238.     DosSleep ( 1000 ) ;
  3239.  
  3240.    /*************************************************************************
  3241.     * Suspend the calibration counter and get the time.                     *
  3242.     *************************************************************************/
  3243.  
  3244.     Parms.Active = FALSE ;
  3245.     GetTime ( &Time[1] ) ;
  3246.     DosWaitThread ( &tidCalibrate, DCWW_WAIT ) ;
  3247.  
  3248.    /*************************************************************************
  3249.     * Return priorities to normal.                                          *
  3250.     *************************************************************************/
  3251.  
  3252.     DosSetPrty ( PRTYS_THREAD, PRTYC_REGULAR, 0, 0 ) ;
  3253.  
  3254.    /*************************************************************************
  3255.     * Get the elapsed time and adjust the calibration count.                *
  3256.     *************************************************************************/
  3257.  
  3258.     ULONG Milliseconds ;
  3259.     ULONG Nanoseconds ;
  3260.     Milliseconds = ComputeElapsedTime ( &Time[0], &Time[1], &Nanoseconds ) ;
  3261.  
  3262.     AdjustedMaxLoad = (double)MaxLoad * 1.0E9 ;
  3263.     AdjustedMaxLoad /= (double)Milliseconds*1.0E6L + (double)Nanoseconds ;
  3264.  
  3265.    /*************************************************************************
  3266.     * Close down the connection to HRTIMER.SYS.                             *
  3267.     *************************************************************************/
  3268.  
  3269.     CloseTimer ( ) ;
  3270.   }
  3271.  
  3272.  /***************************************************************************
  3273.   * Return the adjusted calibration count.  If HRTIMER was not there, it    *
  3274.   *   will be zero.                                                         *
  3275.   ***************************************************************************/
  3276.  
  3277.   return ( (ULONG)AdjustedMaxLoad ) ;
  3278. }
  3279.  
  3280. /****************************************************************************
  3281.  *                                                                          *
  3282.  *                    General Purpose Counter Thread                        *
  3283.  *                                                                          *
  3284.  ****************************************************************************/
  3285.  
  3286. STATIC VOID _Optlink CounterThread ( PVOID Parameter )
  3287. {
  3288.   PCOUNTER_PARMS Parms = PCOUNTER_PARMS ( Parameter ) ;
  3289.  
  3290.   while ( Parms->Active )
  3291.   {
  3292.     (*Parms->Counter) ++ ;
  3293.   }
  3294. }
  3295.  
  3296. /****************************************************************************
  3297.  *                                                                          *
  3298.  *      Open the Profile                                                    *
  3299.  *                                                                          *
  3300.  ****************************************************************************/
  3301.  
  3302. STATIC HINI OpenProfile ( PSZ Name, HAB Anchor, HMODULE Library, HWND HelpInstance )
  3303. {
  3304.  /***************************************************************************
  3305.   * Query the system INI for the profile file's path.                       *
  3306.   ***************************************************************************/
  3307.  
  3308.   PSZ ProfilePath = PSZ(NULL) ;
  3309.   ULONG Size ;
  3310.  
  3311.   if ( PrfQueryProfileSize ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), PSZ("INIPATH"), &Size ) )
  3312.   {
  3313.     // The info exists.  Fetch it.
  3314.     ProfilePath = PSZ ( AllocateMemory ( Size ) ) ;
  3315.     PrfQueryProfileData ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), PSZ("INIPATH"),
  3316.       ProfilePath, &Size ) ;
  3317.  
  3318.     // Build the profile file name.
  3319.     BYTE FullPath [_MAX_PATH] ;
  3320.     strcpy ( PCHAR(FullPath), PCHAR(ProfilePath) ) ;
  3321.     strcat ( PCHAR(FullPath), "\\" ) ;
  3322.     strcat ( PCHAR(FullPath), PCHAR(Name) ) ;
  3323.     strcat ( PCHAR(FullPath), ".INI" ) ;
  3324.  
  3325.     // Clean the name up and expand it to a full path.
  3326.     BYTE Path [256] ;
  3327.     DosQueryPathInfo ( FullPath, FIL_QUERYFULLNAME, Path, sizeof(Path) ) ;
  3328.  
  3329.     // Does the file exist?  If not, discard the name.
  3330.     FILESTATUS3 Status ;
  3331.     if ( DosQueryPathInfo ( Path, FIL_STANDARD, &Status, sizeof(Status) ) )
  3332.     {
  3333.       FreeMemory ( ProfilePath ) ;
  3334.       ProfilePath = PSZ(NULL) ;
  3335.     }
  3336.   }
  3337.  
  3338.  /***************************************************************************
  3339.   * If the profile file couldn't be found, ask the user for a path.         *
  3340.   ***************************************************************************/
  3341.  
  3342.   if ( ProfilePath == NULL )
  3343.   {
  3344.     // Set the default path.
  3345.     BYTE Path [256] ;
  3346.     DosQueryPathInfo ( PSZ("."), FIL_QUERYFULLNAME, Path, sizeof(Path) ) ;
  3347.  
  3348.     // Call up the entry dialog.
  3349.     PROFILE_PARMS Parms ;
  3350.     Parms.id = IDD_PROFILE_PATH ;
  3351.     Parms.hwndHelp = HelpInstance ;
  3352.     Parms.Path = Path ;
  3353.     Parms.PathSize = sizeof(Path) ;
  3354.     if ( WinDlgBox ( HWND_DESKTOP, HWND_DESKTOP, PFNWP(ProfileProcessor),
  3355.       Library, IDD_PROFILE_PATH, &Parms ) )
  3356.     {
  3357.       // If OK, save the approved path in the system profile.
  3358.       ProfilePath = PSZ ( AllocateMemory ( strlen(PCHAR(Path)) + 1 ) ) ;
  3359.       strcpy ( PCHAR(ProfilePath), PCHAR(Path) ) ;
  3360.  
  3361.       PrfWriteProfileData ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), PSZ("INIPATH"),
  3362.         ProfilePath, strlen(PCHAR(ProfilePath))+1 ) ;
  3363.     }
  3364.     else
  3365.     {
  3366.       // If not, return an error.
  3367.       return ( 0 ) ;
  3368.     }
  3369.   }
  3370.  
  3371.  /***************************************************************************
  3372.   * Build the full profile file name.                                       *
  3373.   ***************************************************************************/
  3374.  
  3375.   BYTE ProfileName [_MAX_PATH] ;
  3376.   strcpy ( PCHAR(ProfileName), PCHAR(ProfilePath) ) ;
  3377.   strcat ( PCHAR(ProfileName), "\\" PROGRAM_NAME ".INI" ) ;
  3378.  
  3379.  /***************************************************************************
  3380.   * Release the memory previously allocated to store the path.              *
  3381.   ***************************************************************************/
  3382.  
  3383.   if ( ProfilePath )
  3384.   {
  3385.     FreeMemory ( ProfilePath ) ;
  3386.   }
  3387.  
  3388.  /***************************************************************************
  3389.   * Open/Create the profile file and return the resultant handle.           *
  3390.   ***************************************************************************/
  3391.  
  3392.   return ( PrfOpenProfile ( Anchor, ProfileName ) ) ;
  3393. }
  3394.